# IEEE 754规范
由于计算机的二进制实现和位数限制,有些数无法有限表示。JS 遵循 IEEE 754 规范,采用双精度存储(double precision),占用 64 bit。
- 1位用来表示符号位,如-、+
- 11位用来表示指数,
- 52位表示尾数, 即1-2^51次方
# 0.1 + 0.2 !== 0.3
0.1转为二进制存储时 0.0001 1001 1001 .... 0.2转为二进制存储时 0.0011 0011 0011 ....
可见某些数字在转换为二进制存储时为无限不循环的,由于计算机存储的精度有限制(能存的位数有限),会取一个近似值进行存储,从而导致 0.1 + 0.2不等于0.3。
除了浮点数会出现无限循环导致超出精度限制的情况。 大整数也有可能超出精度限制。
如,9999999999999999 == 10000000000000001 // true
所以,在进行严格的数学运算时,需考虑精度问题
# 处理数学计算
# 浮点数升级整数再作运算
// 浮点升级到整型
function toInt(num) {
if (typeof num !== "number" || isNaN(num)) {
throw new Error("num should be a value number");
}
const numStr = num + "";
const tempArr = numStr.split(".");
const times = tempArr[1] ? tempArr[1].length : 0;
num = tempArr.join("") * 1;
return {
value: num,
times: times,
};
}
function floatAdd(a, b) {
a = parseFloat(a);
b = parseFloat(b);
const coupule = [toInt(a), toInt(b)];
const maxTimes = Math.max(...coupule.map((item) => item.times));
const addResult = coupule.reduce((value, item, index) => {
let itemValue = item.value;
if (item.times !== maxTimes) {
console.log(item.value);
itemValue = (maxTimes - item.times) * 10 * item.value;
}
value += itemValue;
return value;
}, 0);
return addResult / Math.pow(10, maxTimes);
}
floatAdd(0.1, 0.2);//0.3
floatAdd(0.7, 0.1);//0.8
# 使用权威的数学计算库
参考 JS精度丢失问题 (opens new window) JavaScript 深入之浮点数精度 (opens new window)