zoukankan      html  css  js  c++  java
  • js小数点相乘或相除出现多位数的问题

    最近做一个支付的项目需要做个计算器,所以发现了一个问题。

    比如:

    0.03/0.00003=999.9999999999999

    0.0003*0.3=0.000029999999999999997

    0.1+0.2=0.30000000000000004

    等...

    后面查了一下发现原因是:

    浮点数值的最高进度是17位小数,但在进行运算的时候其精确度却远远不如整数;整数在进行运算的时候都会转成10进制; 而Java和JavaScript中计算小数运算时,都会先将十进制的小数换算到对应的二进制,一部分小数并不能完整的换算为二进制,这里就出现了第一次的误差。待小数都换算为二进制后,再进行二进制间的运算,得到二进制结果。然后再将二进制结果换算为十进制,这里通常会出现第二次的误差。

    所以(0.1+0.2)!=03

    直接贴上个方法:

    function toDecimal2(x,ss) { 
          var f = parseFloat(x); 
          if (isNaN(f)) { 
            return false; 
          } 
          var f = Math.round(x*100)/100; 
          var s = f.toString(); 
          var rs = s.indexOf('.'); 
          if (rs < 0) { 
            rs = s.length; 
            s += '.'; 
          } 
          while (s.length <= rs + ss) { 
            s += '0'; 
          } 
          return s; 
        } 
    
    function bcFixed(num, s) {
        var times = Math.pow(10, s)
        var des = num * times + 0.5
        des = parseInt(des, 10) / times
        return toDecimal2(des,s)+'';
    }
    
    /**
     * 加法运算,避免数据相加小数点后产生多位数和计算精度损失。
     *
     * @param num1加数1 | num2加数2
     */
    function bcadd(num1, num2,s) {
     var baseNum, baseNum1, baseNum2,ret;
     try {
      baseNum1 = num1.toString().split(".")[1].length;
     } catch (e) {
      baseNum1 = 0;
     }
     try {
      baseNum2 = num2.toString().split(".")[1].length;
     } catch (e) {
      baseNum2 = 0;
     }
     baseNum = Math.pow(10, Math.max(baseNum1, baseNum2));
    	ret=(num1 * baseNum + num2 * baseNum) / baseNum;
     return bcFixed(ret,s);
    };
    /**
     * 加法运算,避免数据相减小数点后产生多位数和计算精度损失。
     *
     * @param num1被减数  |  num2减数
     */
    function bcsub(num1, num2,s) {
     var baseNum, baseNum1, baseNum2,ret;
     var precision;// 精度
     try {
      baseNum1 = num1.toString().split(".")[1].length;
     } catch (e) {
      baseNum1 = 0;
     }
     try {
      baseNum2 = num2.toString().split(".")[1].length;
     } catch (e) {
      baseNum2 = 0;
     }
     baseNum = Math.pow(10, Math.max(baseNum1, baseNum2));
     precision = (baseNum1 >= baseNum2) ? baseNum1 : baseNum2;
    ret=((num1 * baseNum - num2 * baseNum) / baseNum).toFixed(precision);
     return bcFixed(ret,s);
    };
    /**
     * 乘法运算,避免数据相乘小数点后产生多位数和计算精度损失。
     *
     * @param num1被乘数 | num2乘数
     */
    function bcmul(num1, num2,s) {
     var baseNum = 0,ret;
     try {
      baseNum += num1.toString().split(".")[1].length;
     } catch (e) {
     }
     try {
      baseNum += num2.toString().split(".")[1].length;
     } catch (e) {
     }
     ret=Number(num1.toString().replace(".", "")) * Number(num2.toString().replace(".", "")) / Math.pow(10, baseNum);
     return bcFixed(ret,s);
    };
    /**
     * 除法运算,避免数据相除小数点后产生多位数和计算精度损失。
     *
     * @param num1被除数 | num2除数
     */
    function bcdiv(num1, num2,s) {
     var baseNum1 = 0, baseNum2 = 0,ret;
     var baseNum3, baseNum4;
     try {
      baseNum1 = num1.toString().split(".")[1].length;
     } catch (e) {
      baseNum1 = 0;
     }
     try {
      baseNum2 = num2.toString().split(".")[1].length;
     } catch (e) {
      baseNum2 = 0;
     }
     with (Math) {
      baseNum3 = Number(num1.toString().replace(".", ""));
      baseNum4 = Number(num2.toString().replace(".", ""));
      ret=(baseNum3 / baseNum4) * pow(10, baseNum2 - baseNum1);
     return bcFixed(ret,s);
     }
    };
    

      

    调用方法:(后面的s为显示小数点后几位,比如s为0时显示整数,2为显示两位小数,比如2.00)

    加法:bcadd(num1, num2,s) //如:1+2为 bcadd(1, 2,2)

    减法:bcsub(num1, num2,s) //如:1-2为 bcsub(1, 2,2)

    乘法:bcmul(num1, num2,s) //如:1*2为 bcmul(1, 2,2)

    除法:bcdiv(num1, num2,s)  //如:1/2为 bcdiv(1, 2,s)

  • 相关阅读:
    How to create jar for Android Library Project
    Very large tabs in eclipse panes on Ubuntu
    64bit Ubuntu, Android AAPT, R.java
    Linux(Ubuntu)下如何安装JDK
    Configure xterm Fonts and Colors for Your Eyeball
    建立、配置和使用Activity——启动其他Activity并返回结果
    建立、配置和使用Activity——使用Bundle在Activity之间交换数据
    建立、配置和使用Activity——启动、关闭Activity
    建立、配置和使用Activity——Activity
    异步任务(AsyncTask)
  • 原文地址:https://www.cnblogs.com/gxsyj/p/9397440.html
Copyright © 2011-2022 走看看