为什么 0.1 + 0.1 == 0.2?

Kez*_*zer 5 floating-point precision floating-accuracy

这与Java有关。据我所知,由于二进制表示,Java 无法完美表示 0.1。这使得

0.1 + 0.1 + 0.1 == 0.3
Run Code Online (Sandbox Code Playgroud)

错误的。然而,为什么

0.1 + 0.1 == 0.2
Run Code Online (Sandbox Code Playgroud)

给出真的?

Pas*_*uoq 6

由于二进制表示,Java 无法完美表示 0.1。这使得

0.1 + 0.1 + 0.1 == 0.3

错误的。

这不是相等性错误的全部原因,尽管它是其中的一部分。0.3也不完全是 3/10。碰巧恰好0.2是两次0.1(尽管它们不是分别为 2/10 和 1/10),并且0.1与自身相加产生的值也是您在键入常量 时得到的值0.2。另一方面,您在操作后获得的整体0.1 + 0.1 + 0.1近似值与0.3从 3/10分离的近似值略有不同。

如果我们使用具有 5 个有效数字的十进制,您可能会惊讶于 1 / 3 * 3 == 1 不成立(1 / 3 将计算为 0.33333,而 3 将计算为 0.99999,这与 1 不同),而 1 / 4 * 4 == 1 确实成立(1 / 4 将计算为 0.25,而 4 将计算为 1)。

您的问题与此有些相似,但用于基数为 2 的计算。每一个常数和操作都是一个近似的机会。有时近似值不会发生,有时它们发生但会抵消,因此最终结果比您期望的更准确。在 的情况下0.1 + 0.1,结果不是 2/10,但它与您编写 时得到的 2/10 的近似值相同0.2,因此等式成立。随着0.1 + 0.1 + 0.1我们碰巧没有这么幸运了。

  • @Kezer 二进制浮点中发生的任何事情总是有一个更大的原因:写出二进制数字,操作不得不按照它们的方式行事。在这种情况下,`0.1 + 0.1 == 0.2` 有一个 ** 简单** 更大的原因:如果不发生溢出,则将一个数加到自身或乘以 2 始终是二进制浮点中的精确运算。所以没有由'0.1 + 0.1'中的加法引起的近似。为加法选择的结果是可表示的最接近 2/10 的结果,因为它正好是“0.1”的两倍,也就是最接近 1/10 的结果。 (3认同)