【问题标题】:Why does 0.1 + 0.4 = 0.5?为什么 0.1 + 0.4 = 0.5?
【发布时间】:2018-06-30 16:01:10
【问题描述】:

我们知道floating point is broken,因为十进制数不能总是完美地用二进制表示。它们被四舍五入为一个可以用二进制表示的数字;有时这个数字更高,有时更低。在这种情况下,使用无处不在的IEEE 754 double format 0.1 和 0.4 轮高:

0.1 = 0.1000000000000000055511151231257827021181583404541015625
0.4 = 0.40000000000000002220446049250313080847263336181640625

由于这两个数字都很高,因此您预计它们的总和也会很高。完美的添加应该给你0.5000000000000000277555756156289135105907917022705078125,但你会得到一个很好的精确0.5。为什么?


问题Is floating point math broken? 已在上面确定,但这个问题不同。在考虑该问题的答案时,它要求对非直观结果的进一步详细信息。

【问题讨论】:

  • 相关stackoverflow.com/questions/588004/…(但不重复)
  • 我们知道浮点被破坏了,我们(我们这些知道的人,我认为你属于那个班级)无法知道,因为它不是真的。被打破的是许多程序员对浮点运算的理解。由于这似乎是您提供规范问答的努力,我认为它不应该以这种误导性陈述开头。
  • @HighPerformanceMark 我需要一种方法来表明这不是典型的浮点精度问题,也许我有点过于戏剧化了。它并不是真的要成为规范,这是一个真正的问题,有人问我,我努力想出一个答案。但只要我有答案,我就想我会提出来,让它和其他人争吵。

标签: math floating-point language-agnostic floating-accuracy


【解决方案1】:

这种计算的行为方式是因为加法将结果推入另一个(二进制)数量级。这会在左侧(最重要的一侧)添加一个有效位,因此必须在右侧(最低有效的一侧)减少一个位。

第一个数字0.1 以二进制形式存储为2^-4 == 1/162^-3 == 1/8 之间的数字。第二个数字0.4 以二进制形式存储为2^-2 == 1/42^-1 == 1/2 之间的数字。总和 0.5 是数字 2^-1 == 1/2 或稍大一些。这是数量级的不匹配,可能导致数字丢失。

这里是一个例子,更容易理解。假设我们正在开发一台十进制计算机,它可以在浮点中存储四个十进制数字。假设我们要添加数字10/320/3。这些可能最终存储为

3.334

6.667

这两个都有点高。当我们得到这些数字时,我们预计总和也会有点高,即

10.001

但请注意,我们的结果已经进入了一个新的数量级。完整的结果有五位小数,不适合。所以计算机将结果四舍五入到四位小数并得到总和

10.00

令人惊讶的是10/3 + 20/3 的正确答案。

我在美国高中的化学和物理课上经常遇到同样的事情。当计算移动到一个新的数量级时,会发生精确和有效数字的奇怪事情。

【讨论】:

  • 我喜欢 base-10 示例,它使案例更易于理解。我只是希望它不会像它所照亮的那样令人困惑。
【解决方案2】:

虽然大多数十进制数字需要四舍五入以适应二进制,但有些则不需要。 0.5 可以精确地用二进制表示,因为它是 2-1

浮点不仅仅是二进制,它的精度也有限。以下是精确的总和以及两侧最接近的 IEEE 754 双重可表示数字:

0.5000000000000000277555756156289135105907917022705078125
0.5000000000000000000000000000000000000000000000000000000
0.5000000000000001110223024625156540423631668090820312500

很明显,精确的 0.5 最接近真实总和。 IEEE 754 有关于简单数学运算的规则,这些规则规定了如何进行结果舍入,您通常可以依赖最接近的结果。

【讨论】:

  • 我也不认为这是对标题中提出的问题的非常好的规范答案。它不引用最接近0.10.4 的浮点数的十进制表示。
  • @HighPerformanceMark 我不打算让它成为规范,如果你能更好地解释它,那么请留下答案!
  • 感谢邀请我把头伸进这只狮子的下巴之间。我不确定 SO 或整个 Internet 是否需要另一种解释来说明浮点算术与我们大多数人在学校学习的十进制算术有何不同。更不确定我是写它的人。
猜你喜欢
  • 2015-05-21
  • 2014-09-07
  • 1970-01-01
  • 2013-06-03
  • 1970-01-01
  • 2012-01-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多