乐趣区

FE.ES-终结0.1+0.2,答到点上的那种

随便逛了一下知乎和思否的博文,大都没回答到点上。
I. 浮点数的二进制存储
采用 IEEE 754 规范来存储浮点数:1 位【正负符号】+11 位【指数】+52 位【有效数字】,如下图
由于 0.1.toString(2)=0.0001100110011001100110011001100110011001100110011001101 所以 0.1 = 2^-4 * [1].10011001100110011001100110011001100110011001100110100.2 = 2^-3 * [1].1001100110011001100110011001100110011001100110011010
II. 到底怎么相加
铁律是 52 位有效数字,也就是:
0.1 = 2^-3 * 0.1100110011001100110011001100110011001100110011001101(0)
0.2 = 2^-3 * 1.1001100110011001100110011001100110011001100110011010
sum = 2^-2 * 1.0011001100110011001100110011001100110011001100110011(1)
由于有效数字变成了 53 位,根据 IEEE754 rounding mode 的 Round to Nearest, 若 x 在 a 和 b 之间,选择最低有效位为零的值。
a = 2^-2 * 1.0011001100110011001100110011001100110011001100110011
x = 2^-2 * 1.0011001100110011001100110011001100110011001100110011(1)
b = 2^-2 * 1.0011001100110011001100110011001100110011001100110100
当比较 0.1+0.2 和 0.3 时,实际比较的是
0.1 + 0.2 => 0:01111111101:0011001100110011001100110011001100110011001100110[100]
0.3 => 0:01111111101:0011001100110011001100110011001100110011001100110[011]
转成 10 进制,看上去是:
0.1 + 0.2 => 0.300000000000000044408920985006…
0.3 => 0.299999999999999988897769753748…
结果很明显啦
参考资料:https://stackoverflow.com/que…

退出移动版