为什么 0.1+0.2 !== 0.3
涉及面试题:为什么0.1+0.2 !== 0.3?如何解决该问题?
先说原因,由于JS采用 IEEE754双精度版本(64位),并且只要采用IEEE754的语言都有该问题。
我们知道计算机是通过二进制来储存东西的,那么0.1
在二进制中会表示为
//(0011) 表示循环
0.1 = 2 ^ 1.10011(0011)
1
2
2
我们可以发现,0.1
在二进制中是无限循环的一些数字,其实不只是0.1
,其实很多十进制小数用二进制表示都是无限循环的。这样其实没什么问题,但是JS采用的浮点数标准却会裁掉我们的数字。
IEEE754双精度版本(64位)将64位分为了三段
- 第一位用来表示符号
- 接下来的11位用来表示指数
- 其他的位数用来表示有效位,也就是用二进制表示
0.1
中的10011(0011)
那么这些循环的数字被裁减了,就会出现精度丢失的问题,也就造成了0.1
不再是0.1
了,而是编程了0.100000000000000002
0.100000000000000002 === 0.1 // true
1
那么同样的,0.2
在二进制中也是无限循环的,被裁剪后也失去了精度变成了0.200000000000000002
0.200000000000000002 === 0.2 // true
1
所以两者相加不等于0.3
而是0.300000000000000004
0.1 + 0.2 === 0.30000000000000004 // true
1
那么可能又会有疑问,既然0.1
不是0.1
,那为什么console.log(0.1)
却是正确的呢?
因为在输入内容的时候,二进制被转化成了十进制,十进制又被转化成了字符串,在这个转换的过程中,发生了近似取值的过程,所以打印出来其实是一个近似值,你也可以通过以下代码来验证
console.log(0.100000000000000002) // 0.1
1
说完了为什么,来说说如何解决该问题。解决的办法有很多,这里选用原生提供的方式来最简单的解决该问题
parseFloat((0.1+0.2).toFixed(10)) === 0.3 // true
1