`
zccst
  • 浏览: 3287009 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

踩过的坑2-JS精确计算时的bug

阅读更多
Javascript精确计算时的bug


JS无法进行精确计算的bug

在做CRM,二代审核需求审核详情页面时。需要按比例(后端传类似0.8的小数)把用户输入的数字显示在不同的地方。
在做dubheInvest = invest * (1 - ratio);运算时发现问题。具体如下:
示例代码:

console.log( 1 - 0.8 );  //输出 0.19999999999999996
console.log( 6 * 0.7 );  //输出 4.199999999999999
console.log( 0.1 + 0.2 );  //输出 0.30000000000000004
console.log( 0.1 + 0.7 );  //输出 0.7999999999999999
console.log( 1.2 / 0.2 );  //输出 5.999999999999999
通过上面举出的例子可以看到,原生的js运算结果不一定准确,会丢失精度。
解决方案

解决方案的原理是,将浮点数乘以(扩大)10的n次方倍,把浮点数变为整数后再进行相应的运算,最后将得到的结果除以(缩小)10的n次方倍。
原理示例:

将   console.log(1-0.8);  变为 console.log((1 * 10 - 0.8 * 10) / 10); 即可得到正确的值
根据上述原理,可以封装一些方法出来解决此类问题。如下所示(Math.pow(x, y);表示求x的y次方):
  //加  
  function floatAdd(arg1,arg2){  
       var r1,r2,m;  
       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));  
       return (arg1*m+arg2*m)/m;  
  }  
      
  //减  
  function floatSub(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));  
      //动态控制精度长度  
      n=(r1>=r2)?r1:r2;  
      return ((arg1*m-arg2*m)/m).toFixed(n);  
  }  
       
  //乘  
  function floatMul(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);   
  }   
      
      
  //除 
  function floatDiv(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){}   
        
        r1=Number(arg1.toString().replace(".",""));
   
        r2=Number(arg2.toString().replace(".",""));   
        return (r1/r2)*Math.pow(10,t2-t1);   
  }




如果您觉得本文的内容对您的学习有所帮助,您可以微信:
分享到:
评论
1 楼 851228082 2016-04-12  
加法和减法有问题。
比如
floatAdd(17.9,0.01)
17.909999999999997

减法在arg1*m、arg2*m这一步也会产生不精确。

不过,实现思路是正确,就是先转化为整数再计算。

这是我修改后的函数
/**
* float 加法
*/
  function floatAdd(arg1,arg2){ 
       var r1,r2,m; 
       try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0} 
       try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0} 
       var m =Math.pow(10,Math.max(r1,r2));
       var m1=Math.pow(10,Math.max(r1,r2)-r1); 
       var m2=Math.pow(10,Math.max(r1,r2)-r2); 
      
       var r1_integer=Number(arg1.toString().replace(".",""))*m1;
      
       var r2_integer=Number(arg2.toString().replace(".",""))*m2;  
      
      
       return (r1_integer+r2_integer)/m; 
  }
     
  //减法
  function floatSub(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} 
      var m =Math.pow(10,Math.max(r1,r2));
      var m1=Math.pow(10,Math.max(r1,r2)-r1); 
      var m2=Math.pow(10,Math.max(r1,r2)-r2); 
     
      var r1_integer=Number(arg1.toString().replace(".",""))*m1;
     
      var r2_integer=Number(arg2.toString().replace(".",""))*m2;  
     
      n=(r1>=r2)?r1:r2; 
      return Number(((r1_integer-r2_integer)/m).toFixed(n)); 
     
  }


相关推荐

    chuck-bigjs:解决js计算丢失精确度的bug

    解决了js计算丢失精度的问题,稍微修改了big.js实现了连加,连减,连乘,连除。其他的请参考文档 #安装 npm的安装方式 npm install chuck-bigjs #使用方法 import Big from 'chuck-bigjs'; const number = 2; const ...

    详解js加减乘除精确计算

    JS无法进行精确计算的bug 在做CRM,二代审核需求审核详情页面时。需要按比例(后端传类似0.8的小数)把用户输入的数字显示在不同的地方。 在做dubheInvest = invest * (1 – ratio);运算时发现问题。具体如下: ...

    js中浮点型运算BUG的解决方法说明

    曾经项目用到过的,之前在网上找到此代码,但在特定条件下除法和加法运算依然会出现BUG个人对此稍作优化 代码如下://除法函数,用来得到精确的除法结果//说明:javascript的除法结果会有误差,在两个浮点数相除的...

    JS浮点数运算结果不精确的Bug解决

    最近在做项目的时候,涉及到产品价格的计算,经常会出现JS浮点数精度问题,这个问题,对于财务管理系统的开发者来说,是个非常严重的问题(涉及到钱相关的问题都是严重的问题),这里把相关的原因和问题的解决方案...

    javascript(js)的小数点乘法除法问题详解

    一、用js计算12.32 * 7 结果是多少?答案:86.24000000000001 为什么会出现这种问题?怎么解决?js在处理小数的乘除法的时候有一个bug,解决的方法可以是:将小数变为整数来处理。以上的计算可以改为:12.32 * 100 ...

    Highcharts-Gantt-8.1.2.zip

    当鼠标划过图形时,Highstock 可以将数据点或数据列的信息展示在提示框中,并且提示框会跟随用户的鼠标;我们做了大量工作,可以智能的显示离鼠标最近的点或被遮盖点的信息。 datetime时间轴 Highstock 对时间轴的...

    浅析js中的浮点型运算问题

    js中浮点型是如何运算的呢? 例如:var a=0.69; 我想得到6.9 直接这样写 var c=a*10; alert(c)... //调用:accAdd(arg1,arg2) //返回值:arg1加上arg2的精确结果 function accAdd(arg1,arg

    javascript解决小数的加减乘除精度丢失的方案

    主要介绍了javascript解决小数的加减乘除精度丢失的方案的相关资料以及JavaScript中关于丢失数字精度的问题的探讨,非常的详细,需要的朋友可以参考下

    javascript 小数乘法结果错误的处理方法

    一、用js计算 12.32 * 7 结果是多少? 答案:86.24000000000001   为什么会出现这种问题?怎么解决? js在处理小数的乘除法的时候有一个bug,解决的方法可以是:将小数变为整数来处理。 以上的计算可以改为: ...

    Highcharts-Stock-8.1.2.zip

    当鼠标划过图形时,Highstock 可以将数据点或数据列的信息展示在提示框中,并且提示框会跟随用户的鼠标;我们做了大量工作,可以智能的显示离鼠标最近的点或被遮盖点的信息。 datetime时间轴 Highstock 对时间轴的...

    asoft签到管理系统tykq3.5_build20110125

    2、修正自由签到用户无法计算请假时间、导致无法请假的BUG 3、修正设置得无公共审批人无法在审批人列表中被看到的BUG 4、修正销假后,在请假时间内依然被记录为旷工,其中: 4.1 更改请假逻辑 请假状态从请假...

    js中Number数字数值运算后值不对的解决方法

    我Google了一下,发现原来这是JavaScript浮点运算的一个bug。 比如:7*0.8 JavaScript算出来就是:5.6000000000000005 解决方法:网上找到了一些解决办法,就是重新写了一些浮点运算的函数。 下面就把这些方法摘录...

    Highcharts-8.1.2.zip

    当鼠标划过图形时,Highcharts 可以将数据点或数据列的信息展示在提示框中,并且提示框会跟随用户的鼠标;我们做了大量工作,可以智能的显示离鼠标最近的点或被遮盖点的信息。 datetime时间轴 75% 的直角坐标系...

    站长工具完整无错版 v2.6.rar

    3、修正其它已知BUG  站长工具功能简介 1、JS加密/解密(将代码以js形式进行加密或解密。) 2、UTF-8编码转换工具(UTF-8编码转换。) 3、Unicode编码转换工具(Unicode编码转换。) 4、友情链接(通过本工具...

Global site tag (gtag.js) - Google Analytics