为什么交换相加的几个数的顺序,却得到了不同的和?
23.53 + 5.88 + 17.64 = 47.05
23.53 + 17.64 + 5.88 = 47.050000000000004
在 java 和 javascript 中,都返回了相同的值。
我知道计算机中用二进制浮点形式来表示小数,有很多比如 1/3 - 0.333333…都不能正确的表示。
也许这个问题有点儿傻,但是我想知道为什么仅仅交换了运算的顺序,却产生了不同的结果?谢谢大家。
也许这个问题有点儿傻,但是我想知道为什么仅仅交换了运算的顺序,却产生了不同的结果?
当我们对数值进行四舍五入时,会丢失掉部分精度。让我们先看一个不是二进制浮点数的例子。在此例子中,我们使用 4 位有效数字来描述,如果此范围无法表示,则我们将其向无穷大的方向舍入到最接近的值,这样我们可以清楚的看到在哪个步骤我们丢失掉了精度。
1/3 + 2/3 + 2/3 = (0.3333 + 0.6667) + 0.6667
= 1.000 + 0.6667 (不需要四舍五入!)
= 1.667 (这里 1.6667 被四舍五入到 1.667)
2/3 + 2/3 + 1/3 = (0.6667 + 0.6667) + 0.3333
= 1.333 + 0.3333 (这里 1.3334 被四舍五入到 1.333)
= 1.666 (这里 1.6663 被四舍五入到 1.666)
下面的例子中,我们使用整数:
10000 + 1 - 10000 = (10000 + 1) - 10000
= 10000 - 10000 (这里 10001 被四舍五入到 10000)
= 0
10000 - 10000 + 1 = (10000 - 10000) + 1
= 0 + 1
= 1
上面的例子已经很清楚的说明了这个问题了,就是因为我们需要有限的有效数字——不是一个有限的小数位数。如果我们总是保持相同的有限的位数,然后使用加法或者减法操作,将不会出现问题(如果没有溢出的话)。
问题是,当计算过程中遇到了更大的数,那么较小的数就会丢失,比如上例子的 10001
被四舍五入到 10000
。