ntscshen / ntscshen.github.io

个人博客
0 stars 2 forks source link

为什么 `0.1+0.2 != 0.3 ` ? #18

Open ntscshen opened 5 years ago

ntscshen commented 5 years ago

结论:由于浮点数运算的精度问题导致的。

为什么1:在计算机运算过程中,浮点数会通过 IEEE 754 标准进行转换,由于标准本身尾数位数有限制,需要将后面多余的尾数为截掉,所以在进制转换的时候精度已经损失了

为什么2:let x = 0.1 能得到真正的 0.1,标准中规定尾数的最大长度是53位,它最大可表示的是 2^53次方(9007199254740992)长度是16位, 0.1.toPrecision(16) -> "0.1000000000000000" 0.1.toPrecision(20) -> "0.100000000000000005551115123126" 这么看的话,在赋值时的 0.1 其实并不是真正意义上的 0.1,是意义上的 0.1 尾数的前16位。

结论就这样,那么如何去比较这道题呐?可以使用 JavaScript 提供的最小精度值,Number.EPSILON console.log(Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON); 检查等式左右两边差的绝对值是否小于 JS 中的最小精度,才是正确比较浮点树的方法。

实际开发中如何解决精度问题
    // 相加时简单的情况下,一个函数即可解决
    function add(num1, num2) {
     const num1Digits = (num1.toString().split('.')[1] || '').length;
     const num2Digits = (num2.toString().split('.')[1] || '').length;
     const baseNum = Math.pow(10, Math.max(num1Digits, num2Digits));
     return (num1 * baseNum + num2 * baseNum) / baseNum;
    }
可以使用第三方类库:Math.js

参考: 05 | JavaScript类型:关于类型,有哪些你不知道的细节? https://juejin.im/post/5b90e00e6fb9a05cf9080dff