就像十进制里 1/3 = 0.333... 无限循环一样,0.1 在二进制里也是无限循环的。
但计算机内存有限,不能存无限长的数字,必须在某个位置截断。JavaScript 用的是 IEEE 754 双精度浮点数,只有 64 位,其中 52 位用来存小数部分。
截断就意味着误差。
哪些数能精确表示?
能被 2 的幂次整除的小数,在二进制里都能精确表示:
// 这些都是精确的
0.5 = 1/2 = 0.1 (二进制)
0.25 = 1/4 = 0.01 (二进制)
0.125 = 1/8 = 0.001 (二进制)
0.0625 = 1/16 = 0.0001 (二进制)
function isEqual(a, b) {
return Math.abs(a - b) < Number.EPSILON;
}
console.log(isEqual(0.1 + 0.2, 0.3)); // true
// 0.1 + 0.2
const result = (0.1 * 10 + 0.2 * 10) / 10; // 0.3
// 封装一下
function add(a, b) {
const precision = Math.max(
(a.toString().split('.')[1] || '').length,
(b.toString().split('.')[1] || '').length
);
const factor = Math.pow(10, precision);
return (Math.round(a * factor) + Math.round(b * factor)) / factor;
}
console.log(add(0.1, 0.2)); // 0.3
const result = parseFloat((0.1 + 0.2).toFixed(10));
console.log(result); // 0.3
// decimal.js
import Decimal from 'decimal.js';
const a = new Decimal(0.1);
const b = new Decimal(0.2);
console.log(a.plus(b).toString()); // "0.3"