zoukankan      html  css  js  c++  java
  • [转]解决JS浮点数(小数)计算加减乘除的BUG

    [转]解决JS浮点数(小数)计算加减乘除的BUG

    问题这样的:

      37.5*5.5=206.08  (JS算出来是这样的一个结果,我四舍五入取两位小数)

      我先怀疑是四舍五入的问题,就直接用JS算了一个结果为:206.08499999999998

      怎么会这样,两个只有一位小数的数字相乘,怎么可能多出这么小数点出来。

      我Google了一下,发现原来这是JavaScript浮点运算的一个bug。

      比如:7*0.8 JavaScript算出来就是:5.6000000000000005

      网上找到了一些解决办法,就是重新写了一些浮点运算的函数。

      下面就把这些方法摘录下来,以供遇到同样问题的朋友参考:

      

       程序代码

    //除法函数,用来得到精确的除法结果

    // 说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。

    //调用:accDiv(arg1,arg2)

    //返回值:arg1除以arg2的精确结果

     function accDiv(arg1, arg2) {

            var t1 = 0, t2 = 0, r1, r2;

            try { t1 = arg1.toString().split(".")[1].length } catch (e) { }

            try { t2 = arg2.toString().split(".")[1].length } catch (e) { }

            with (Math) {

                r1 = Number(arg1.toString().replace(".", ""))

                r2 = Number(arg2.toString().replace(".", ""))

                return (r1 / r2) * pow(10, t2 - t1);

            }

        }

    //给Number类型增加一个div方法,调用起来更加方便。

    Number.prototype.div = function(arg) {

            return accDiv(this, arg);

        }

    //乘法函数,用来得到精确的乘法结果

    //说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。

    //调用:accMul(arg1,arg2)

    //返回值:arg1乘以 arg2的精确结果

    function accMul(arg1, arg2) {

            var m = 0, s1 = arg1.toString(), s2 = arg2.toString();

            try { m += s1.split(".")[1].length } catch (e) { }

            try { m += s2.split(".")[1].length } catch (e) { }

            return Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m)

        }

    // 给Number类型增加一个mul方法,调用起来更加方便。

    Number.prototype.mul = function(arg) {

            return accMul(arg, this);

        }

    //加法函数,用来得到精确的加法结果

    //说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。

    //调用:accAdd(arg1,arg2)

    // 返回值:arg1加上arg2的精确结果

    function accAdd(arg1, arg2) {

            var r1, r2, m, c;

            try { r1 = arg1.toString().split(".")[1].length } catch (e) { r1 = 0 }

            try { r2 = arg2.toString().split(".")[1].length } catch (e) { r2 = 0 }

            c = Math.abs(r1 - r2);
            m = Math.pow(10, Math.max(r1, r2))
            if (c > 0) {
                var cm = Math.pow(10, c);
                if (r1 > r2) {
                    arg1 = Number(arg1.toString().replace(".", ""));
                    arg2 = Number(arg2.toString().replace(".", "")) * cm;
                }
                else {
                    arg1 = Number(arg1.toString().replace(".", "")) * cm;
                    arg2 = Number(arg2.toString().replace(".", ""));
                }
            }
            else {
                arg1 = Number(arg1.toString().replace(".", ""));
                arg2 = Number(arg2.toString().replace(".", ""));
            }
            return (arg1 + arg2) / m

        }

    //给Number类型增加一个add方法,调用起来更加方便。

     Number.prototype.add = function(arg) {

            return accAdd(arg, this);

        }

    //减法函数,用来得到精确的减法结果

    //说明:javascript的减法结果会有误差,在两个浮点数相减的时候会比较明显。这个函数返回较为精确的减法结果。

    //调用:accSub(arg1,arg2)

    // 返回值:arg1加上arg2的精确结果

    function accSub(arg1,arg2){
       var r1,r2,m,n;
       try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0}
       try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0}
       m=Math.pow(10,Math.max(r1,r2));
       //last modify by deeka
       //动态控制精度长度
       n=(r1>=r2)?r1:r2;
       return ((arg1*m-arg2*m)/m).toFixed(n);
    }

     
      在你要用的地方包含这些函数,然后调用它来计算就可以了。

      比如你要计算:7*0.8 ,则改成 (7).mul(8)

      其它运算类似,就可以得到比较精确的结果。

  • 相关阅读:
    使用 Spring data redis 结合 Spring cache 缓存数据配置
    Spring Web Flow 笔记
    Linux 定时实行一次任务命令
    css js 优化工具
    arch Failed to load module "intel"
    go 冒泡排序
    go (break goto continue)
    VirtualBox,Kernel driver not installed (rc=-1908)
    go运算符
    go iota
  • 原文地址:https://www.cnblogs.com/zmc/p/2920184.html
Copyright © 2011-2022 走看看