格式化数字 - Java 中的小数位数字分组

Posted

技术标签:

【中文标题】格式化数字 - Java 中的小数位数字分组【英文标题】:Formatting numbers - grouping of decimal-place digits in Java 【发布时间】:2021-05-17 01:09:06 【问题描述】:

DecimalFormat 类是否支持小数位数分组,类似于通过方法 setGroupingUsed()setGroupingSize 对数字的整数部分进行分组?

我希望将数字 123456.789012 格式化为 123,456.789,012

【问题讨论】:

你试过了吗? 我还没有听说这样做过。这是任何特定国家/地区的标准数字格式吗?如果是这样,您是否尝试过使用该国家/地区的语言环境? 我从未见过这样的格式。 更常见的格式是 123,456.789012 有趣的是,Wikipedia 文章有这样的说法:“在某些国家,这些‘数字组分隔符’仅用于小数分隔符的左侧;在其他国家,它们也用于用长小数部分分隔数字。”然而,这篇文章没有提到哪些国家使用每种风格。 【参考方案1】:

根据API guide:

分组分隔符通常用于千位,但在某些情况下 它分隔一万个国家。分组大小是一个常数 分组字符之间的位数,例如 3 表示 100,000,000 或 4 对应 1,0000,0000。如果你提供一个模式 多个分组字符,最后一个和之间的间隔 整数的结尾是使用的那个。所以“#,##,###,####”== "######,####" == "##,####,####"。

这段话表明分组符号只能应用于数字的整数部分。如果我们设置这样的模式:

String pattern = "###,###.###,###";

并将其传递给DecimalFormat的实例,结果为:

java.lang.IllegalArgumentException: Malformed pattern "###,###.###,###"

而更典型的:

String pattern = "###,###.###";

按预期工作。

setGroupingUsed 不适用,因为它需要一个布尔值来指示数字是否将用分组数字表示。 setGroupingSize 也不适用,因为它只控制每个组的位数。

获得所需内容的唯一方法是推出自己的格式化程序。

附录:

破解DecimalFormat的source会发现要格式化的数字分为三部分:leftDigits,或数字整数部分最左边的数字zeroDigits,或最右边的数字数字的整数部分,rightDigits,或数字的小数部分。

代码包括以下内容(注释从第 2507 行开始):

// The position of the last grouping character is
// recorded (should be somewhere within the first two blocks
// of characters)

注释中的“块”显然是指leftDigitszeroDigits,因此即使是开发人员也认为分组数字只会出现在整数部分,并且没有规定在小数部分进行分组(除了抛出例外)。

【讨论】:

这真是令人失望。对我来说,小数点右侧每 3 位有逗号看起来很正常。我本来希望 DecimalFormat 开箱即用。 @DawoodibnKareem 出于好奇,您是否熟悉哪些国家或行业在数字的小数部分使用分组数字?除了每五位数用稀疏空间分组的数学家之外,我在网上找不到任何东西。 ISO 标准似乎是用点或逗号来表示用于分组的小数和细空格,但它没有提到在小数部分进行分组。 精美呈现! 不,我真的不是。实际上,我对这个问题下的三个 cmets 感到非常惊讶 - 其中两个评论员否认看到/听到了这个,一个说它比省略逗号更常见。【参考方案2】:

小数点后没有分组。这样的格式会无效并抛出异常。

【讨论】:

什么代码会抛出异常,什么异常? 小数点后的逗号

以上是关于格式化数字 - Java 中的小数位数字分组的主要内容,如果未能解决你的问题,请参考以下文章

DecimalFormat(数字格式)

java中 DecimalFormat格式的定义

java中 DecimalFormat格式的定义

在Java中格式化带有小数位的数字符号而不进行除法的正确方法

Java 格式化数字--- DecimalFormat

Java中的紧凑数字格式化行为(在十进制和科学记数法之间自动切换)