八度舍入和评估顺序

Octave Rounding and Evaluation Order

八度我得到

1 - 0.05 -0.95 = 0

1 - 0.95 -0.05 = 4.1633e-17

我理解是求值顺序结合近似二进制表示造成的 0.05 作为 0.00(0011) 和 0.95 作为 0.11(1100) 有人可以给我完整的故事或给我看 link 解释吗?

---编辑: 此问题不是 Why is 24.0000 not equal to 24.0000 in MATLAB? 的重复,其他人将其识别为可能的重复。后者处理数字的舍入表示。前者询问计算执行顺序影响结果精度的机制的细节。

完整解释

What Every Computer Scientist Should Know About Floating-Point Arithmetic

https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

Matzeri 的 link 关于浮点运算的权威资源确实是这个问题的权威答案。但是,要完成:

octave:34> fprintf("%.80f\n%.80f\n", 0.95, 1 - 0.05)
0.94999999999999995559107901499373838305473327636718750000000000000000000000000000
0.94999999999999995559107901499373838305473327636718750000000000000000000000000000

octave:35> fprintf("%.80f\n%.80f\n", 0.05, 1 - 0.95)
0.05000000000000000277555756156289135105907917022705078125000000000000000000000000
0.05000000000000004440892098500626161694526672363281250000000000000000000000000000

换句话说,0.95 不太容易用浮点数精确表示,因此第一步中涉及 0.95 的任何计算(无论是作为输入还是作为输出)都必然不如仅使用 0.05 的计算精确.

因此:

1 - 0.05 = 0.95 (imprecise, due to intrinsic floating-point representation)
(1 - 0.05) - 0.95 = exactly 0 (since both are represented identically imprecisely)

vs

1 - 0.95 = imprecise 0.05 (due to involvement of 0.95 in calculation)
(imprecise 0.05) - (precise 0.05) = not exactly 0 (due to difference in precisions)

然而。应该指出的是,这种精度差异远低于机器公差(在我的机器上由 eps -- 2.2204e-16 返回)。因此,对于所有的实际应用,4.1633e-170。如果这里的实际点是测试一个计算的结果是否为effectively 0,那么实际上在处理浮点计算时应该始终考虑机器精度,或者最好找到一种方法来重新表述您的问题,从而完全避免进行相等性测试。