JS浮点数精准计算问题

在工作中遇到这种浮点数计算精度问题,例如
0.1 + 0.2不等于0.3

1
2
>  0.1+0.2
<· 0.30000000000000004

原因

在 JavaScript 里,数字均为基于 IEEE 754 标准的双精度 64 位的浮点数,并且只要采用 IEEE 754 的语言都有该问题。


sign bit(符号): 用来表示正负号

exponent(指数): 用来表示次方数

mantissa(尾数): 用来表示精确度

六十四位中符号位占一位,整数位占十一位,其余五十二位都为小数位,也就是说一个数字的范围只能在 -(2^53 -1) 至 2^53 -1 之间。
0.1 + 0.2 算不准的原因也在于此。浮点数用二进制表达时是无穷的,且最多 53 位,必须截断,进而产生误差。最简单的解决办法就是放大一定倍数变成整数,计算完成后再缩小。不过更稳妥的办法是使用下文将会提到的 math.js 等工具库。

解决办法

  1. 取巧方法 ~

    1
    parseFloat((0.1+0.2).toFixed(2)); //js浮点计算bug,取两位小数精度
  2. 将数字转成整数,但是这种方法对大数支持的依然不好

    1
    2
    3
    4
    5
    6
    function addFloatNum(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;
    }
  3. 第三方库 Math.js , bignumber.js,big.js