问题 为什么DecimalFormat“。#”和“0。#”在23.0上有不同的结果?


为什么 java.text.DecimalFormat 评估以下结果:

new DecimalFormat("0.#").format(23.0)        // result: "23"

new DecimalFormat(".#").format(23.0)         // result: "23.0"

我本来期待结果 23 在这两种情况下,因为特殊的性格 # 省略零。领导特殊角色如何? 0 影响分数部分? (尝试将其与javadoc中给出的BNF匹配/理解,但未能这样做。)


6644
2018-03-22 15:17


起源

我怀疑是否 ".#" 是一种有效的格式,如果它不应该 #.#,这也导致了 23。 - Tom
@Tom:DecimalFormat(“。0”)也可以。在javadoc中没有看到任何禁止“。#”之类的内容。 - MGn
“在javadoc中没有看到任何禁止像”#“的内容。 我也不是,但这并不意味着代码可以正确处理这个问题。还有那个 DecimalFormat(".0") 作品可以巧合 .# 要么 .0 无效,“后备”只打印数字,因为它会导致相同的字符串("23.0")。但同样,这只是猜测。 - Tom
标题说15,示例代码使用23. :) - hamena314
不再 ;-) - Bathsheba


答案:


第二种格式似乎无效 的JavaDoc,但无论如何它无错误地解析。

 Pattern:
         PositivePattern
         PositivePattern ; NegativePattern
 PositivePattern:
         Prefixopt Number Suffixopt
 NegativePattern:
         Prefixopt Number Suffixopt
 Prefix:
         any Unicode characters except \uFFFE, \uFFFF, and special characters
 Suffix:
         any Unicode characters except \uFFFE, \uFFFF, and special characters
 Number:
         Integer Exponentopt
         Integer . Fraction Exponentopt
 Integer:
         MinimumInteger
         #
         # Integer
         # , Integer
 MinimumInteger:
         0
         0 MinimumInteger
         0 , MinimumInteger
 Fraction:
         MinimumFractionopt OptionalFractionopt
 MinimumFraction:
         0 MinimumFractionopt
 OptionalFraction:
         # OptionalFractionopt
 Exponent:
         E MinimumExponent
 MinimumExponent:
         0 MinimumExponentopt

在这种情况下,我希望格式化程序的行为是未定义的。也就是说,它可能产生任何旧的东西,我们不能依赖于任何方式的一致性或有意义。所以,我不知道你为什么得到23.0,但是你可以认为在代码中你应该避免这是无稽之谈。

更新: 我刚刚通过Java 7的DecimalFormat库运行调试器。代码不仅明确地说'。#'是允许的,那里有一个注释(java.text.DecimalFormat:2582-2593),它表示允许它,以及一个允许它的实现(第2597行)。这似乎违反了该模式记录的BNF。

鉴于这不是记录在案的行为,你真的不应该依赖它,因为它可能会在Java版本甚至库实现之间发生变化。


7
2018-03-22 16:13





以下源评论解释了相当不直观的处理 ".#"。在我的行中3383-3385行 DecimalFormat.java file(JDK 8)有以下注释:

// Handle patterns with no '0' pattern character. These patterns
// are legal, but must be interpreted.  "##.###" -> "#0.###".
// ".###" -> ".0##".

似乎开发人员已经选择解释 ".#" 如 ".0##"而不是你的预期("0.#")。


3
2018-03-22 16:49



我只是看看DecimalFormat的源代码并看到了这一点。 - callyalater
我已经在答案中记录了这一点,但我有不同的行号。我想知道导致这种差异的原因是什么?您还没有提到您在这里引用的java版本。你可以补充一点,因为它可能是负责任的吗? - Engineer Dollery
我正在使用JDK 8,这就是区别。 - MicSim