为什么0.1 + 0.4 = 0.5?

时间:2018-01-22 04:05:27

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

我们知道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?,但这个问题不同。在考虑该问题的答案时,它要求对非直观结果进一步详细说明。

2 个答案:

答案 0 :(得分:4)

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

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

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

3.334

6.667

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

10.001

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

10.00

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

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

答案 1 :(得分:3)

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

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

0.5000000000000000277555756156289135105907917022705078125
0.5000000000000000000000000000000000000000000000000000000
0.5000000000000001110223024625156540423631668090820312500

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