为什么 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

我们可以发现,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
上次更新: 9/25/2019, 9:41:46 AM