zoukankan      html  css  js  c++  java
  • 实现js浮点数加、减、乘、除的精确计算(网上很多文章里的方法是不能解决所有js浮点数计算误差的)

      最近做项目,要用到js的加、减、乘、除的计算,发现js浮点数计算会有一些误差。

      网上有很多文章都有js浮点数计算误差的解决方法,说能解决这个问题,But……。比如一个加法函数,如下:

    1 function accAdd(arg1,arg2){ 
    2 var r1,r2,m; 
    3 try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0} 
    4 try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0} 
    5 m=Math.pow(10,Math.max(r1,r2)) 
    6 return (arg1*m+arg2*m)/m 
    7 }

        此方法在很多人的博客里都有,也有很多人转摘,不知道他们是否真正的使用了,真正的进行了测试,这个方法是不能解决所有js浮点数计算误差的,比如:alert(accAdd(268.34,0.83));

      由于项目要用,所以参考了一些思路与方法,对js的加、减、乘、除的精确计算方法进行了如下处理,废话不多说,代码如下:

    (function () {
        var calc = {
            /*
            函数,加法函数,用来得到精确的加法结果   
            说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。 
            参数:arg1:第一个加数;arg2第二个加数;d要保留的小数位数(可以不传此参数,如果不传则不处理小数位数)
            调用:Calc.Add(arg1,arg2,d)   
            返回值:两数相加的结果
            */
            Add: function (arg1, arg2) {
                arg1 = arg1.toString(), arg2 = arg2.toString();
                var arg1Arr = arg1.split("."), arg2Arr = arg2.split("."), d1 = arg1Arr.length == 2 ? arg1Arr[1] : "", d2 = arg2Arr.length == 2 ? arg2Arr[1] : "";
                var maxLen = Math.max(d1.length, d2.length);
                var m = Math.pow(10, maxLen);
                var result = Number(((arg1 * m + arg2 * m) / m).toFixed(maxLen));
                var d = arguments[2];
                return typeof d === "number" ? Number((result).toFixed(d)) : result;
            },
            /*
            函数:减法函数,用来得到精确的减法结果   
            说明:函数返回较为精确的减法结果。  
            参数:arg1:第一个加数;arg2第二个加数;d要保留的小数位数(可以不传此参数,如果不传则不处理小数位数
            调用:Calc.Sub(arg1,arg2)   
            返回值:两数相减的结果
            */
            Sub: function (arg1, arg2) {
                return Calc.Add(arg1, -Number(arg2), arguments[2]);
            },
            /*
            函数:乘法函数,用来得到精确的乘法结果   
            说明:函数返回较为精确的乘法结果。  
            参数:arg1:第一个乘数;arg2第二个乘数;d要保留的小数位数(可以不传此参数,如果不传则不处理小数位数)
            调用:Calc.Mul(arg1,arg2)   
            返回值:两数相乘的结果
            */
            Mul: function (arg1, arg2) {
                var r1 = arg1.toString(), r2 = arg2.toString(), m, resultVal, d = arguments[2];
                m = (r1.split(".")[1] ? r1.split(".")[1].length : 0) + (r2.split(".")[1] ? r2.split(".")[1].length : 0);
                resultVal = Number(r1.replace(".", "")) * Number(r2.replace(".", "")) / Math.pow(10, m);
                return typeof d !== "number" ? Number(resultVal) : Number(resultVal.toFixed(parseInt(d)));
            },
            /*
            函数:除法函数,用来得到精确的除法结果   
            说明:函数返回较为精确的除法结果。  
            参数:arg1:除数;arg2被除数;d要保留的小数位数(可以不传此参数,如果不传则不处理小数位数)
            调用:Calc.Div(arg1,arg2)   
            返回值:arg1除于arg2的结果
            */
            Div: function (arg1, arg2) {
                var r1 = arg1.toString(), r2 = arg2.toString(), m, resultVal, d = arguments[2];
                m = (r2.split(".")[1] ? r2.split(".")[1].length : 0) - (r1.split(".")[1] ? r1.split(".")[1].length : 0);
                resultVal = Number(r1.replace(".", "")) / Number(r2.replace(".", "")) * Math.pow(10, m);
                return typeof d !== "number" ? Number(resultVal) : Number(resultVal.toFixed(parseInt(d)));
            }
        };
        window.Calc = calc;
    }());
    

      目前以上代码在项目中使用,还没有发现有什么问题。如果你觉得有问题或有具体的数据验证有问题,请联系!

  • 相关阅读:
    POJ3159 Candies —— 差分约束 spfa
    POJ1511 Invitation Cards —— 最短路spfa
    POJ1860 Currency Exchange —— spfa求正环
    POJ3259 Wormholes —— spfa求负环
    POJ3660 Cow Contest —— Floyd 传递闭包
    POJ3268 Silver Cow Party —— 最短路
    POJ1797 Heavy Transportation —— 最短路变形
    POJ2253 Frogger —— 最短路变形
    POJ1759 Garland —— 二分
    POJ3685 Matrix —— 二分
  • 原文地址:https://www.cnblogs.com/junjieok/p/3306155.html
Copyright © 2011-2022 走看看