Open goldEli opened 4 years ago
由于计算机只认识二进制,所以在进行计算时,计算机需要把十进制转换成二进制。
计算机根据已知对照表,采用拼凑法对十进制进行转换。
整数二进制对照表 | 十进制 | 二进制 |
---|---|---|
1 | 1 | |
2 | 10 | |
4 | 100 | |
8 | 1000 | |
16 | 10000 | |
32 | 100000 |
小数二进制对照表
十进制 | 二进制 |
---|---|
0.5 | 0.1 |
0.25 | 0.01 |
0.125 | 0.001 |
0.0625 | 0.0001 |
0.03125 | 0.00001 |
举几个例子试试:
转换8:
通过对照表得到1000。
转换7:
没有直接对应的,会在表中找比7小,且相邻的4,7-4=3,剩下的3也没有对应的,找到2,3-2=1,剩下的1可在表上直接找到。
所以
7 = 4 + 2 + 1 = 100 + 10 + 1 = 111
转换0.625:
同上可以分解为 0.5 + 0.125
0.625 = 0.5 + 0.125 = 0.1 + 0.01 = 0.11
最后我们来看看0.1 + 0.2 为什么不等于 0.3:
0.1 和 0.2 在对照表中都不能拼凑出来,所以 0.2只能拼出近似值:
0.2 = 1/8 + 1/16 + 1/128 + 1/256 + 1/512
= 0.201171875
如果不用拼凑法,用不断乘2的算法去计算 0.2 的二进制,是个无线循环的二进制,由于 IEEE 754 双精度。六十四位中符号位占一位,整数位占十一位,其余五十二位都为小数位。只能对0.2的二进制进行四舍五入,最终导致结果失真
计算中为了避免失真的问题,可以先转成整数计算后再转成小数。也可以用 js 原生的解决办法。
parseFloat(0.1+0.2).toFixed(10)
0.1+0.2为什么不等于0.3? 从数学上来说,肯定是相等的,但是我们要知道,计算机中的数字表示是不一样的,计算机中的数字,是由二进制表示的。
我们知道,十进制1转化成二进制是1,2是10, 3是11 ... 那么小数的十进制如何转化成二进制呢?参考十进制的小数怎么转换成二进制,例如0.125转化成二进制就是0.001
js中,数字是由双精度64位浮点数来存储的,什么叫双精度浮点数?我们把一个数字拆分开来看:
符号占一位 | 指数占11位 | 尾数占52位 |
---|
总结来说,0.1转化成二进制,是一个无限循环的数,0.2同样也是一个无限循环的数,所以在计算机中,而且他们的尾数超过了52位,就无法精确的计算出来结果。所以0.1+0.2是两个无限循环的二进制数在进行加法运算,所以得出来的结果,当然不等于0.3了。
0.1+0.2 === 0.3 // false