为什么0.1 + 0.4 = 0.5?

Mar*_*som 7 language-agnostic math floating-point floating-accuracy

我们知道浮点数被打破了,因为十进制数不能总是用二进制来完美表示.它们四舍五入到可以用二进制表示的数字; 有时这个数字更高,有时它更低.在这种情况下,使用无处不在的IEEE 754双格式,高0.1和0.4:

0.1 = 0.1000000000000000055511151231257827021181583404541015625
0.4 = 0.40000000000000002220446049250313080847263336181640625
Run Code Online (Sandbox Code Playgroud)

由于这两个数字都很高,你可以期望它们的总和也很高.完美的添加应该会给你0.5000000000000000277555756156289135105907917022705078125,但你会得到一个很好的确切0.5.为什么?


问题浮点数学是否破碎?已经在上面确定了,但这个问题是不同的.在考虑该问题的答案时,它要求对非直观结果进一步详细说明.

Ror*_*ton 5

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

第一个数字0.1以二进制形式存储在2^-4 == 1/16和之间2^-3 == 1/8。第二个数字0.4以二进制形式存储在2^-2 == 1/4和之间2^-1 == 1/2。总和0.5为数字2^-1 == 1/2或更大一点。这是幅度上的不匹配,并可能导致数字丢失。

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

3.334
Run Code Online (Sandbox Code Playgroud)

6.667
Run Code Online (Sandbox Code Playgroud)

两者都有点高。当我们得到这些数字时,我们期望总和也有点高,即

10.001
Run Code Online (Sandbox Code Playgroud)

但请注意,我们的结果已迈上了一个新的台阶。完整的结果有五个十进制数字,将不适合。因此计算机将结果四舍五入为四位十进制数字并获得总和

10.00
Run Code Online (Sandbox Code Playgroud)

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

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


Mar*_*som 2

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

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

0.5000000000000000277555756156289135105907917022705078125
0.5000000000000000000000000000000000000000000000000000000
0.5000000000000001110223024625156540423631668090820312500
Run Code Online (Sandbox Code Playgroud)

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

  • 感谢邀请我把头伸进这只狮子的嘴里。我不确定 SO 或整个互联网是否需要另一种解释来解释浮点算术与我们大多数人在学校学到的十进制算术有何不同。更不确定我是不是写这篇文章的人。 (2认同)