前端架构系列

0.1+0.2不等于0.3

2020-06-13  本文已影响0人  羽晞yose

在计算机里,所有的数据都会转化为二进制被存储
而0.1和0.2是十进制,它们需要转换为二进制被存储

先以整数为例
10转化为二进制就是1010,怎么算出来的?
1 * 2^3 + 0 * 2² + 1 * 2^1 + 0 * 2 = 8+2 = 10
反过来说,1010总共有四位,第一位为0乘以2的零次方,第二位为1乘以2的一次方,以此方式计算下去

那么小数又是如何计算的
以0.5来说,就是1乘以2的负一次方
小数点后的二进制计算规律为:位数越往后计算方式为2的负N次方,N递减1

那么0.1转换成2进制又是怎么算的?
当然用上面的N递减1来算很麻烦,所以真正使用的是乘2取整法
以0.1为例:

0.1 * 2 = 0.2; // 无整数,填0 => 0.0
0.2 * 2 = 0.4; // 无整数,填0 => 0.00
0.4 * 2 = 0.8; // 无整数,填0 => 0.000
0.8 * 2 = 1.6; // 去整数,填1,余0.6 => 0.0001
0.6 * 2 = 1.2; // 去整数,填1,余0.2 => 0.00011
0.2 * 2 = 0.4; // 无整数,填0 => 0.000110

根据上面的结果可以看出,0.1转化为二进制会是一个无限循环小数(双精度浮点数),而计算机不可能一直存储下去,所以会在限定位数取整(IEEE 754 标准的 64 位双精度浮点数的小数部分最多支持53位二进制位)

0.1.toString(2); // 0.0001100110011001100110011001100110011001100110011001101

正常规律讲,其实后面依然为0011,但是长度已经超过最大值,所以对下一位进行取整,由于下一位是1,所以最后一位则从0变为1,因此实际存储结果会比0.1更大一些
0.0001100110011001100110011001100110011001100110011001101 // 取整后
0.000110011001100110011001100110011001100110011001100110011 // 正常结果

0.2也是如此,其结果依然会比0.2大一些

0.2.toString(2); // 0.001100110011001100110011001100110011001100110011001101

那么0.1的二进制 加上 0.2的二进制,其结果就为
0.0100110011001100110011001100110011001100110011001100111
该值转为10进制,则结果为0.30000000000000004

所以,0.1+0.2不等于0.3
参考文章:为什么在JavaScript中0.1+0.2不等于0.3?


== 和 === 的区别?

===会比较数据类型,那么什么时候会用到双等号呢?
null == undefined的时候

上一篇下一篇

猜你喜欢

热点阅读