【问题标题】:Why doesn't 0.9 recurring always equal 1为什么 0.9 循环不总是等于 1
【发布时间】:2013-10-17 20:02:59
【问题描述】:

在数学上,可以证明 0.9 循环等于 1。然而,这个问题与无穷大、收敛或这背后的数学无关。

上面的假设可以用 C# 中的双精度表示,如下所示。

var oneOverNine = 1d / 9d;
var resultTimesNine = oneOverNine * 9d;

使用上面的代码,(resultTimesNine == 1d) 的计算结果为 true。

当使用小数代替时,评估结果为假,但是,我的问题不是关于双精度和小数的不同精度。

既然没有类型具有无限精度,那么 double 如何以及为什么能保持这样的相等性,而小数则没有?关于oneOverNine 变量在内存中的存储方式,上面代码的“字里行间”到底发生了什么?

【问题讨论】:

  • 我假设会发生舍入。对于向1.0 的双打,对于远离它的浮动。
  • 什么版本的 C#、编译器和操作系统?询问是因为在 64 位 Win7 机器上使用 VS2010 为我提供了 true 浮点数和双精度数,无论是 x86 还是 x64。
  • @JoelRondeau Fair 问题,在我当前的机器(VS2010,Win7 x64)上,我得到的结果与您相同,但十进制错误,所以同样,精度差异,但比较有趣。跨度>
  • 从不同机器上的相同代码得到不同的答案让我想起了这个 Lippert 答案:stackoverflow.com/a/8795656/154766

标签: c# .net math


【解决方案1】:

这取决于用于获得最接近 1/9 的可表示值的舍入。它可以去任何一种方式。您可以在 Rob Kennedy 的有用页面上调查可表示性问题:http://pages.cs.wisc.edu/~rkennedy/exact-float

但不要认为 double 能够以某种方式达到精确性。它不是。如果您尝试使用 2/9、3/9 等,您会发现舍入相反的情况。底线是 1/9 不能完全用二进制浮点表示。因此会发生舍入,并且您的计算会出现舍入错误。

【讨论】:

    【解决方案2】:

    关于 oneOverNine 变量在内存中的存储方式,上面代码的字面意思是“行间”发生了什么?

    您要问的是IEEE 754。这是 C#、底层 .Net 运行时以及大多数其他编程平台用于存储和操作十进制值的规范。这是因为对 IEEE 754 的支持通常直接在 CPU/芯片组级别实现,这使得它比仅在软件中实现的替代方案具有更高的性能,并且在构建编译器时更容易,因为这些操作几乎直接映射到特定的 CPU 指令.

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-28
      • 1970-01-01
      • 1970-01-01
      • 2019-06-06
      相关资源
      最近更新 更多