最近在学习JS过程中发现在计算机JS时发现了一个非常有意思事,0.1+0.2的结果不是0.3,而是0.30000000000000004,但先将小数做乘法然后相加,再除回来就得到想要的0.3
我用python试了一下,发现python也是一样的,结果也是0.30000000000000004。
然后我开始信息搜集,最后找到了答案。想知道这其中的原因,要先理解这些点:二进制、指数形式、IEEE 754标准。
1、二进制
在计算机中所有的数据都是二进制形式存储的,包括整数、浮点数以及其他所有类型的数据。我们将十进制的0.1以及0.2转换成二进制
转换的方法也比较简单,整数转换成二进制:就是用整数除以2然后从下往上取余数,下图用100举例
然后小数转换成二进制就是,小数部分无限乘以2,然后顺序取整。下图用0.375举例
2、指数形式
用指数方式表示可以在有限的空间里存储更大的数值。
所有的十进制数都可以用指数形式表示,成为D=M*10E,比如100可以表示为1*102。
二进制数也可以用指数形式表示,B=M*2E的形式,这里的E为指数,M为B的位数。比如0.011可以表示为1.1*10-10,这里的“-10”表示的是-2。
3、浮点数IEEE754标准
JavaScript中所有数字包括整数和小数都只有一种类型,是遵循 IEEE 754 标准,使用64位固定长度来表示,也就是标准的 double 双精度浮点数。
这里第一位为符号位“1”表示负数,“0”表示正数
一、首先将十进制的0.1转换成二进制:0.0011001100110011......
然后将十进制的0.2转换成二进制:0.0011001100110011........
二、将二进制的0.1和0.2转换成指数形式
十进制:0.1
二进制形式:0.000110011001100110011......
指数形式:1.10011001100110011......*2-100 //指数是-4
十进制:0.2
二进制形式:0.001100110011001100110011......
指数形式:1.100110011001100110011......*2-11 //指数是-3
三、将指数形式转换为IEEE754标准
这里由于IEEE754标准规定了尾数只能保留52位,所以无限循环小数需要做四舍五入,只保留52位小数(就是第53位以后全部舍弃,第53位“0舍1入”,而当第52位为1时,还得再进一位)
将十进制0.2转换成IEEE 754标准:
四、使用IEEE 754形式的 0.1+0.2
这块太长了,简单写的话应该就是10.0100100100100100100100100100100......100111,但是此时得到的数指数依然是指数形式,要将它转换成为二进制形式,就是将小数点向前移三位变成0.01001001001001001001001.....00111
然后将这个数转换为十进制数就是0*2-1+1*2-2+0*2-3+0*2-4.......+1*2-52之后就可以得到0.30000000000000004了
总结一下就是:
计算机存储数据时由于空间有限,所以只能存储固定长度的数据,而像一些无限循环的数据只能被四舍五入,所以一些数据可能会和它本身有一些误差,所以做相加运算也会有误差。
那么最后再看一下(0.1*10+0.2*10)/10为什么等于3,由于0.1和0.2先做乘法运算所以就变成了整数,所以再来看一下整数之间的加法。
最后再用3/10就得到了0.3,这个怎么算我还没琢磨,就直接计算器吧 -..-
来源:https://www.cnblogs.com/hai-long/p/12552148.html