美文网首页前端技术前端知识
JavaScript 如何解决数字计算的精度问题

JavaScript 如何解决数字计算的精度问题

作者: 一俢 | 来源:发表于2019-02-23 10:33 被阅读7次

    我们前端在做计算过程中,特别时小数的计算,都会遇到意想不到的结果,通常我们在价格的计算中遇到很多问题,这是由于 JS 中的 Number 类型是一个浮点类型。

    Nubmer 类型

    我们先看看 JS 中的 Number 类型。它并不像其它的语言有不同的数字类型,例如:整型、长整型、浮点类型等等,定义不同的数字类型存储的空间也不一样。然而 JS 中的 Number 类型都是浮点类型并且存储空间为 8 数节(byte)(8*8 bit位)。其中Number 类型值的整数最多15位,小数最多17位。

    注:1byte=8bit,1kb=1024byte,1mb=1024kb

    精度问题

    JS 中的 Number 是一个双精度浮点类型,双精度浮点类型在 64 位存储空间中的内容如下:

    todo:

    1位 11位 52位
    符号位 指数位 小数位
    0表示正,1表示负 -1022~+1023 任意

    由于计算机在计算的过程中,会把十进制数字先转换成二进制,然后做运算,因为浮点类型的小数位的限制而截断了运算完的二进制,这时候再把它转换成了十进制就产生了精度的问题。

    举个例子:
    0.1 + 0.2 = ?

    • 0.1 转换成二进制:0.000110011001100110....
    • 0.2 转换成二进制:0.001100110011001100....
    • 0.000110011001100110.... + 0.001100110011001100.... = 0.0100110011001100110011001100110011001100110011001100...还很多,如果超过了 52 位就截断了。
    • 然后转换成十进制:0.30000000000000004

    如何解决精度问题

    简单的四舍五入

    通过简单的四舍五入可以解决一些问题。

    (0.1 + 0.2).toFixed(1);//0.3
    

    换算成整型计算

    当然这种四舍五入的方式明显是经不起考验的。彻底消除运算过程中的精度,需要将所有数字升位转化为整型了再做计算,计算完毕后再将最终结果进行相应的降位处理。

    function add(num1, num2) {
       var p1 = 0;
       var p2 = 0;
    
       if (num1.toString().split('.').length > 1) {
           p1 = num1.toString().split('.')[1].length;
       }
    
       if (num2.toString().split('.').length > 1) {
           p2 = num2.toString().split(".")[1].length;
       }
    
       var p = p1 > p2 ? p1 : p2;
    
       var n1 = num1 * Math.pow(10, p);
       var n2 = num2 * Math.pow(10, p);
    
       var result = (n1 + n2) / Math.pow(10, p);
    
       return result;
    }
    
    add(0.1, 0.2);//0.3
    

    相关文章

      网友评论

        本文标题:JavaScript 如何解决数字计算的精度问题

        本文链接:https://www.haomeiwen.com/subject/zzbuyqtx.html