学习一道面试题。

目录

  1. 核心
  2. 2进制与10进制之间转换
  3. 0.5转成二进制
  4. 0.1转换成二进制是什么
  5. 结论

计算机运算时只能识别二进制数值,即所有运算中的数字都是有无数个0和1组成的。

0.1+0.2运算之前也是先分别将十进制小数转成二进制后,进行加法运算,将得到的二进制数与十进制小数0.3转成二进制数进行比较。

由于十进制小数0.1和0.2转成二进制后无穷尽,根据双精度浮点数规则,计算机会将其截断,四舍五入,所以相加得到的二进制数会0.3直接转成二进制数大一些。

所以会出现0.1+0.2为什么不等于0.3。

核心

十进制小数如何转化为二进制数值

二级制数值相加规则,满2进1

2进制与10进制之间转换

2——>10: parseInt(11, 2) // 3

10——>2: 10.toString(2) // ‘1010’

整数之间的进制转换还是比较简单的,那么小数呢?

0.5转成二进制

0.5 = n2^-1 + m2^-2 + …

左右两边同时乘2

1 = n2^0 + m2^-1 + …

由于从2^0开始,才会有整数部分,此时我们就可以看出

1 = n*2^0

n = 1

所以,得到结果:十进制的0.5转换成二进制后为2^-1,那么0.1转换成二进制是什么呢

0.1转换成二进制是什么

0.1 = n2^-1 + m2^-2 + …

0.2 = n2^0 + m2^-1 + … // 由于左边没有整数,所以 n=0, 此时最后结果的首位推导出为0

0.4 = … + a2^0 + b2^-1 + … // 由于左边仍没有整数,所以此时最后结果推导出为00

0.8 = … + a2^0 + b2^-1 + … // 由于左边仍没有整数,所以此时最后结果推导出为000

1.6 = … + a2^0 + b2^-1 + … // 由于左边有整数,所以此时 a = 1, 最后结果推导出为0001

0.6 2 = …+ b2^0 + c*2^1 + … // 由于左边有整数,所以此时 b = 1, 最后结果推导出为00011

如此推导,得到0.1的二进制表示为:00011001100110011…

由上可以知道,0.1的二进制结果,是无穷尽的小数,计算机内会对最后的结果,在一定的小数位时,四舍五入。

计算机计算0.1的二进制时就已经准确了,那么计算0.2,以及最后相加的结果与0.3相比较,就会出现0.1 + 0.2 != 0.3的情况

结论

0.1+0.2不等于0.3是因为计算机将小数转化为2进制时,由于部分小数无穷尽,进行运算时计算机会四舍五入,无法得到期待结果所对应的2进制表示