为啥 DecimalFormat ".#" 和 "0.#" 在 23.0 上有不同的结果?
Posted
技术标签:
【中文标题】为啥 DecimalFormat ".#" 和 "0.#" 在 23.0 上有不同的结果?【英文标题】:Why does DecimalFormat ".#" and "0.#" have different results on 23.0?为什么 DecimalFormat ".#" 和 "0.#" 在 23.0 上有不同的结果? 【发布时间】:2016-03-22 15:17:42 【问题描述】:为什么java.text.DecimalFormat
会评估以下结果:
new DecimalFormat("0.#").format(23.0) // result: "23"
new DecimalFormat(".#").format(23.0) // result: "23.0"
在这两种情况下,我都希望结果是 23
,因为特殊字符 #
省略了零。前导特殊字符0
如何影响小数部分? (试图用 javadoc 中给出的 BNF 来匹配/理解它,但没有这样做。)
【问题讨论】:
我想知道".#"
是否是一个有效的格式,如果它不应该是#.#
,这也会导致23
。
@Tom: DecimalFormat(".0") 也可以。在 javadoc 中没有看到任何禁止“.#”之类的内容。
“在 javadoc 中没有看到任何禁止“.#”之类的东西的内容 我也没有,但这并不意味着代码可以正确处理这个问题。当.#
或.0
无效并且“回退”只打印数字时,DecimalFormat(".0")
的工作可能是巧合,因为它会产生相同的字符串 ("23.0"
)。但同样,这只是一个猜测。
标题说 15,示例代码使用 23。:)
我的错 :) 谢谢@Bathsheba!
【参考方案1】:
根据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 版本甚至库实现之间发生变化。
【讨论】:
【参考方案2】:以下源注释解释了对".#"
的相当不直观的处理。我的DecimalFormat.java
文件(JDK 8)中的第 3383-3385 行有以下注释:
// Handle patterns with no '0' pattern character. These patterns
// are legal, but must be interpreted. "##.###" -> "#0.###".
// ".###" -> ".0##".
似乎开发人员选择将 ".#"
解释为 ".0##"
,而不是您所期望的 ("0.#"
)。
【讨论】:
我只是在查看 DecimalFormat 的源代码并看到了这个。 我已经在我的回答中记录了这一点,但我有不同的行号给你。我想知道是什么导致了这种差异?您还没有提到您在此处引用的 java 版本。您能否为了清楚起见添加它,因为它可能是负责任的? 我使用的是 JDK 8,这就是区别。以上是关于为啥 DecimalFormat ".#" 和 "0.#" 在 23.0 上有不同的结果?的主要内容,如果未能解决你的问题,请参考以下文章
DecimalFormat("0.0") 返回以逗号而不是点作为分隔符的数据[重复]