0.1+0.2!==0.3

158 阅读1分钟

原因

JavaScript只有一种数字类型:Number,它的实现遵循IEEE 754标准,使用64位固定长度表示(标准的double双精度浮点数)。在二进制科学表示法中,双精度浮点数的小数部分最多只能保留52位。剩余的遵从‘0舍1入’原则舍去。 0.1 的二进制值是个无限循环小数,精度丢失,所以 0.1 + 0.2 !== 0.3。

整数的十进制转二进制的规则:

整数

÷2取余,倒序排列,高位补0(计算机内部表示数是定长的:8位、16位、32位)。

负整数

  • 把正整数转成二进制
  • 对二进制取反
  • 对取反后的二进制加1(补码?)

小数

  • 小数部分*2
  • 取结果的整数部分
  • 结果的小数部分*2
  • 取结果的整数部分
  • 直到小数部分为0或者位数与小数位数到达一定精度
  • 正序排列 0.1和0.2都是无限循环的,存储时只能通过近似值存储,造成误差。

解决

toFixed()

toFixed() 方法可把 Number 四舍五入为指定小数位数的数字 (0.1+0.2).toFixed(4)===0.3.toFixed(4)

设置误差范围(机器精度)——Number.EPSILON

x = 0.2;
y = 0.3;
z = 0.1;
equal = (Math.abs(x - y + z) < Number.EPSILON);

Number.EPSILON 属性表示 1 与Number可表示的大于 1 的最小的浮点数之间的差值。 EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16,或者 2^-52。

参考资料