Double.ToString() 的奇怪行为

Posted

技术标签:

【中文标题】Double.ToString() 的奇怪行为【英文标题】:Weird behaviour of Double.ToString() 【发布时间】:2014-05-27 06:27:09 【问题描述】:

我正在尝试将双精度值 9007199254740992.0 转换为字符串。

但是好像有四舍五入的错误(最后2变成了0):

(9007199254740992.0).ToString("#")    // Returns "9007199254740990"
(9007199254740992.0).ToString()       // Returns"9.00719925474099E+15"

首先我认为这个数字可能无法表示为双精度数。但它可以。这可以通过将其转换为 long 然后将其转换为字符串来看到。

((long)9007199254740991.0).ToString() // Returns "9007199254740991"
((long)9007199254740992.0).ToString() // Returns "9007199254740992"

另外,我发现如果我使用"R" format,它可以工作。

(9007199254740992.0).ToString("R")    // Returns "9007199254740992"

谁能解释为什么ToString("#") 不以全精度返回整数部分的双精度数?

【问题讨论】:

【参考方案1】:

可以在MSDN上看到:

默认情况下,返回值只包含15位精度 尽管内部维护了最多 17 位数字。如果值 此实例的位数大于 15 位,ToString 返回 PositiveInfinitySymbol 或 NegativeInfinitySymbol 而不是 预期数量。如果您需要更高的精度,请指定格式 “G17”格式规范,它总是返回 17 位 精度或“R”,如果数字可以是,则返回 15 位数字 如果数字只能是,则以该精度或 17 位表示 以最高精度表示。

【讨论】:

有趣。因此,如果您想将双精度数转换为字符串,并且您不知道它有多少位精度,则应始终使用“R”或“G17”(如果精度对您很重要)。这肯定是一个陷阱——我花了很多时间弄清楚我的代码失败的原因。感谢您的回复。 :) @AndersKellerCarstensen 确实如此。另请参阅C# double to decimal precision loss 中的另一个问题。这是设计使然。它们折叠所有不同的double 值,其字符串表示形式与"G15" 格式相同。这会失去精度。

以上是关于Double.ToString() 的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

Rails 4 link_to方法::post和remote:真正的奇怪行为

python规范化奇怪的行为

日期时间的奇怪行为

Firebase 查询结果 SWIFT 的奇怪行为

如果分数不能以二进制精确表示,Double.toString() 如何工作?

decimal and double ToString problem