js 小数运算不精确
所有的计算机语言都有这样的问题, 问题根源在于计算机对于小数的存储和我们想的不一样。
js
0.3 - 0.2; // 0.09999999999999998
小数如何转换二进制, 乘 2 取整, 顺序排列。
0.125 转二进制
js
0.125 * 2 = 0.25; // 0
0.25 * 2 = 0.5; // 0
0.5 * 2 = 1.0; // 1
0.125.toString(2) === '0.001';
0.2 转二进制
0.2
循环的二进制小数
js
0.2 * 2 = 0.4 // 0
0.4 * 2 = 0.8 // 0
0.8 * 2 = 1.6 // 1
0.6 * 2 = 1.2 // 1
0.2 * 2 = 0.4 // 0, 和第一行重复了
//...
0.2.toString(2) // 0.001100110011001100110011001100110011001100110011001101
十进制
js
314 = 3 * 10^2 + 1 * 10^1 + 4 * 10^0;
3.14 = 3 * 10^0 + 1 * 10^-1 + 4 * 10^-2;
二进制
js
101 = 1 * 2^2 + 0 * 2^1 + 1 * 2^0 = 5;
1.101 = 1 * 2^0 + 1 * 2^-1 + 0 * 2^-2 + 1 * 2^-3 = 1.625;
1.625.toString(2) === "1.101";
十进制小数的末尾是 5
, 则转换成二进制肯定不会丢失精度。
js
(1.5).toString(2); // "1.1"
(1.25).toString(2); // "1.01"
(1.4).toString(2); // '1.011001100110011001100110011001100110011001100110011'
所以 0.3
转换为二进制不精确, 0.2
转换为二进制也不精确, 所以它们相减也不精确。