问题背景
当我们被问到0.1+0.2等于多少时肯定会想到是0.3啊,在数学角度是正确的,但浏览器里确不是等于。如下图:
解决问题
分析出现上诉问题的原因
我们都知道,计算机是通过二进制的方式存储数据的,所以计算机计算0.1+0.2的时候,实际上是计算的两个数的二进制的和。0.1的二进制是0.0001100110011001100...(1100循环),0.2的二进制是:0.00110011001100...(1100循环),这两个数的二进制都是无限循环的数。那JavaScript是如何处理无限循环的二进制小数呢?
JavaScript中所用的数字包括整数和小数,但是只有一种类型——Number,它的实现遵循IEEE 754标准,使用64位固定长度来表示,也就是标准的double双精度浮点数。在二进制科学表示法中,双精度浮点数的小数部分最多只能保留52位,再加上前面的1,其实就是保留53位有效数字,剩余的舍去,遵从“0舍1入”的原则。
怎么解决问题
// 方案1 toFixed(不推荐)
parseFloat((0.1+0.2).toFixed(1)) === 0.3 //true
// 但是 多为小数不准确
parseFloat((0.1+0.25).toFixed(1)) === 0.3 //true
// 最终解决方案
Number.EPSILON=(function(){ //解决兼容性问题
return Number.EPSILON?Number.EPSILON:Math.pow(2,-52);
})();
//上面是一个自调用函数,当JS文件刚加载到内存中,就会去判断并返回一个结果,相比
//if(!Number.EPSILON){
// Number.EPSILON=Math.pow(2,-52);
//}这种代码更节约性能,也更美观。
function numbersequal(a,b){
return Math.abs(a-b)<Number.EPSILON;
}
//接下来再判断
var a=0.1+0.2, b=0.3;
console.log(numbersequal(a,b)); //这里就为true了