Javascript浮点数运算的精度问题

421 阅读2分钟

前言

javascript数字运算过程中经常发现的问题,如下:

原因

JavaScript 里的数字是采用 IEEE 754 标准的 64 位双精度浮点数。该规范定义了浮点数的格式,对于64位的浮点数在内存中的表示,最高的1位是符号位,接着的11位是指数,剩下的52位为有效数字,具体:

  • 第0位:符号位, s 表示 ,0表示正数,1表示负数;
  • 第1位到第11位:储存指数部分, e 表示 ;
  • 第12位到第63位:储存小数部分(即有效数字),f 表示,

计算过程

十进制的0.1和0.2都会被转换成二进制,但由于浮点数用二进制表达时是无穷的,IEEE 754 标准的 64 位双精度浮点数的小数部分最多支持 53 位二进制位,因浮点数小数位的限制而截断的二进制数字,再转换为十进制,就成了 0.30000000000000004。所以在进行算术计算时会产生误差。

解决办法

  • 两个大数相加的处理方式:

如果直接相加的结果:

采用如下方式相加:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Javascript大数相加</title>
</head>

<body>
    <script>
        class MyMath {
            constructor() {

            }
            add(params1, params2) {
                var charsArr1 = params1.split('');
                var charsArr2 = params2.split('');
                var resultArr = [];
                let len1 = charsArr1.length;
                let len2 = charsArr2.length;
                var maxLen = Math.max(len1, len2);
                var carry = 0;
                for (let i = maxLen - 1; i >= 0; i--) {
                    var p1 = 0,
                        p2 = 0,
                        s, s1;
                    if (len1 - 1 >= i) {
                        p1 = parseInt(charsArr1[i]);
                    }
                    if (len2 - 1 >= i) {
                        p2 = parseInt(charsArr2[i]);
                    }
                    s = p1 + p2 + carry;
                    if (s >= 10) {
                        carry = 1;
                        s1 = parseInt(s.toString().split('')[1]);
                    } else {
                        carry = 0;
                        s1 = s;
                    }
                    resultArr.push(s1);
                    if (i == 0 && carry == 1) {
                        resultArr.push(carry);
                    }
                }
                var resultStr = resultArr.reverse().join('');
                console.log(resultStr);
            }
        }
        var myClass = new MyMath();
        var result = myClass.add('105222222222222222222222222', '105222222222222222222222221');
    </script>

</body>

</html>

运算结果如下:

  • 1、加法的处理
  • 2、减法的处理
  • 3、乘法的处理
  • 4、除法的处理