0.1 + 0.2 === 0.3 // false

104 阅读1分钟
console.log(0.1+0.2); // 0.30000000000000004JS当中,Number类型实际上是double类型,运算小数时存在精度问题。因为计算机只认识二进制,在进行运算时,需要将其他进制的数值转换成二进制,然后再进行计算

小数用二进制表达时是无穷的。

// 将0.1转换成二进制
console.log(0.1.toString(2)); // 0.0001100110011001100110011001100110011001100110011001101

// 将0.2转换成二进制
console.log(0.2.toString(2));  // 0.001100110011001100110011001100110011001100110011001101
双精度浮点数的小数部分最多支持53位二进制位,所以两者相加后,因浮点数小数位的限制而截断的二进制数字,再转换为十进制,就成了0.30000000000000004,这样在进行算术计算时会产生误差。

ES6Number对象上面,新增一个极小的常量Number.EPSILON。根据规格,它表示1与大于1的最小浮点数之间的差。对于64位浮点数来说,大于1的最小浮点数相当于二进制的1.00..001,小数点后面有连续51个零。这个值减去1之后,就等于2的-52次方。

Number.EPSILON === Math.pow(2, -52)
// true
Number.EPSILON
// 2.220446049250313e-16
Number.EPSILON.toFixed(20)
// "0.00000000000000022204"
Number.EPSILON实际上是JavaScript能够表示的最小精度。误差如果小于这个值,就可以认为已经没有意义了,即不存在误差了。

引入一个这么小的量的目的,在于为浮点数计算,设置一个误差范围。我们知道浮点数计算是不精确的。

Number.EPSILON可以用来设置能够接受的误差范围。比如,误差范围设为2的-50次方(即Number.EPSILON * Math.pow(2, 2)),即如果两个浮点数的差小于这个值,我们就认为这两个浮点数相等。

(0.1 + 0.2 - 0.3) < Number.EPSILON // true