为什么JavaScript里面0.1+0.2 === 0.3是false
我们需要有以下基础知识:
1.计算机将所有数据以二进制的形式存储。
2.计算机用有限的大小来存储数据(因为现实生活中不存在无限大的内存或硬盘)。
结论:十进制的 0.1 转为二进制,得到一个无限小数:
0.0001100110011001100110011001100110011001100110011001101
也就是说,二进制无法用有限的位数来表示 0.1。对于 0.2 也是一样的,不赘述。
二进制能用有限的位数表示的有:0.5、0.25、0.125 等。
总结
1.问题的根源是十进制小数转为二进制小数的过程中,会损失精度
2.你在写代码的过程中,遇到小数都要小心,比如下面的代码会造成死循环
let i = 0.1
while(i!=1){
console.log(i)
i += 0.1
}
在JavaScript的新规范ES6加入了一个新的东西–>Number.EPSILON
EPSILON:希腊字母表的第5个字母 ε
Number.EPSILON是在Number对象上面,新增一个极小的常量。根据规格,它表示 1 与大于 1 的最小浮点数之间的差。
对于 64 位浮点数(double)来说,大于 1 的最小浮点数相当于二进制的 1.00…001 ,小数点后面有连续 51 个零。这个值减去 1 之后,就等于 2 的-52 次方。
Number.EPSILON
2.220446049250313e-16
Math.pow(2, -52)
2.220446049250313e-16
5.551115123125783e-17 < Number.EPSILON * Math.pow(2, 2) // true
Number.EPSILON 可以用来设置“能够接受的误差范围”。
比如,误差范围设为 2 的-50 次方(即 Number.EPSILON * Math.pow(2, 2) ),
即如果两个浮点数的差小于这个值,我们就认为这两个浮点数相等。
function withinErrorMargin (left, right) {
return Math.abs(left - right) < Number.EPSILON * Math.pow(2, 2);
}
0.1 + 0.2 === 0.3 // false
withinErrorMargin(0.1 + 0.2, 0.3) // true
1.1 + 1.3 === 2.4 // false
withinErrorMargin(1.1 + 1.3, 2.4) // true
//上面的代码为浮点数运算,部署了一个误差检查函数。
参考:
为什么 0.1 + 0.2 结果为 0.30000000000000004
为什么JavaScript里面0.1+0.2 === 0.3是false