第46题 关于0.1+0.2!=0.3浮点数计算分析与解决方法
出现的原因
小数点在计算机中是以二进制表示,而有些小数用二进制表示是无穷,所以才会出现上面这种精确度的问题。 一些浮点数表示成二进制
十进制 二进制
0.1 0.0001 1001 1001 1001 ...
0.2 0.0011 0011 0011 0011 ...
0.3 0.0100 1100 1100 1100 ...
0.4 0.0110 0110 0110 0110 ...
0.5 0.1
0.6 0.1001 1001 1001 1001 ...
运行一下下面代码
输入 输出
0.1+0.05==0.15 FALSE
1-0.1-0.1-0.1==0.7 FALSE
0.3/0.1 == 3 FALSE
1.0-0.6 == 0.4 True
1.0-0.5 == 0.5 True
1.0-0.4 == 0.6 True
1.0-0.3 == 0.7 True
1.0-0.2 == 0.8 True
出现这个问题的原因,其实是因为数值的表示在计算机内部是用二进制的。例如,十进制的0.625,换成二进制表示就是
0.101(1*2-1+0*2-2+1*2-3)。0.625这个数倒还好,刚好可以准确表示出来。但如果是0.1的话呢,换成二进制就是0.00011(0011无限循环),也就是:0.000110011001100110011001100110011...,位数是无限的,只能取近似。对于这些不能准确表示的数就有可能会出现这个问题。为什么是可能呢?因为有些数的计算结果,例如0.1+0.3,它虽然也是不能精确地表示,但是它结果足够接近0.4,那取了近似后就成了0.4了。
解决方法
使用简单点四舍五入方法,取了一个10位小数
function numTofixed(num) {
if (typeof num === 'number') {
// 01 + 0.2 = 0.30000000000000004 截取小数点后10位。利用parseFloat去掉小数点后面的0
num = parseFloat(num.toFixed(10))
}
return num;
}
numTofixed(0.1 + 0.2);
