2

在js中,会经常的遇到浮点数精度问题(0.1+0.2),我们都知道是因为转换成二进制的时候产生无限循环小数,而js的尾数部分只能保存52位,出现截取取一舍零造成的;但是现在深挖一下:

const s = 0.1
console.log(s)//s=0.1    

console.log(0.1+5)//5.1

上述代码,s确准确的等于0.1,并没有出现精度不准确的情况,资料上说明,超过16位会使用toPrecision(16) 进行运算,进而会有 s=0.1的情况,那为什么0.1+0.2 不会做toPrecision的运算呢?

而对于第二种情况,我的猜测是对于整数和小数的相加,js会做toPrecision(m+1),m为小数的10的-m次方;
以上是我在研究js精度问题产生的两个问题,能够查到的博客上都对这两个方面没有说明,希望晓得js精度处理机制的大神帮助解答一下,谢谢大家!

补充:对于toPrecision(m)方法什么时候调用,更重要的是 m 的值是如何确定的?

1月5日提问

查看全部 3 个回答

-1

对于你的问题,我在《你不知道JS》中卷第二章2.3.2 看到过这样的说法:

0.1+0.2 === 0.3 //false

从数学角度来说,上面的判断条件应该为true,可结果为什么是false呢?
简单来说,二进制浮点数中的0.1和0.2并不是十分准确,他们相加的结果并非刚好等于0.3,而是一个比较接近的数字 0.30000000000000004,所以条件判断结果为false。有兴趣可以去看看《你不知道JS》

推荐答案

2

JS 的数学运算都是基于 IEEE754 标准的浮点数运算,就算是5+0.1也都是浮点数5+浮点数0.1
造成误差的原因就是取一舍零造成的误差不可被简单忽略。

5+0.1 === 5.1或其它类似的数学运算成立,是因为两边结果的浮点数真的就是相等了(符号位、阶数、尾数全部相同,也可能是细微的不同但是精度处理过后相同不过我不确定)。

   (5+0.1).toPrecision(20) === (5.1).toPrecision(20)
// "5.0999999999999996447" === "5.0999999999999996447"

   (0.1+0.2).toPrecision(20) !== (0.3).toPrecision(20)
// "0.30000000000000004441"  !== "0.29999999999999998890"
超过16位会使用toPrecision(16) 进行运算

这个也并不定是对的,具体精度处理规则我也并不清楚,得看标准才行,有空我再去查查。

0.1+0.2  // 0.30000000000000004

(0.1+0.2).toPrecision(17)
// "0.30000000000000004"


0.3+0.5  // 0.8

0.8.toPrecision(17)
// "0.80000000000000004"

推广链接