JS浮点数精度缺失问题

先看一个例子

alert(0.7+0.1);//输出0.7999999999999999
alert(0.6+0.2);//输出0.8

第二个正确,但第一个是什么鬼,那这是js的错误吗?当然不是。减法乘法之类的也会有这个问题。

你的电脑做着正确的二进制浮点运算,但问题是你输入的是十进制的数,电脑以二进制运算,这两者并不是总是转化那么好的,有时候会得到正确的结果,但有时候就不那么幸运了。

你输入两个十进制数,转化为二进制运算过后再转化回来,在转化过程中自然会有精度损失了。

但一般的损失往往在乘除运算中比较多,而JS在简单的加减法里也会出现这类问题,你也看到了,这个误差也是非常小的,但是却是不该出现的。

如何避免这个问题呢,一般会采用扩大倍数法来解决

如0.001+0.0002,可以都乘以10的4次方,变为10+2=12,再除以10的4次方12/10000=0.0012.把浮点数转换为整数进行运算,然后再转换回来,避免精度缺失。


 
    // 两个浮点数求和

    function accAdd(num1,num2){
       var r1,r2,m;
       try{
           r1 = num1.toString().split('.')[1].length; //取浮点数小数点后的位数
       }catch(e){
           r1 = 0; //异常处理,避免程序运行不下去
       }
       try{
           r2 = num2.toString().split(".")[1].length;
       }catch(e){
           r2=0;
       }
       m=Math.pow(10,Math.max(r1,r2));   //Math.pow(x,y)取x的y次方  
       return Math.round(num1*m+num2*m)/m;
    }
    
    // 两个浮点数相减

    function accSub(num1,num2){
       var r1,r2,m;
       try{
           r1 = num1.toString().split('.')[1].length;
       }catch(e){
           r1 = 0;
       }
       try{
           r2 = num2.toString().split(".")[1].length;
       }catch(e){
           r2=0;
       }
       m=Math.pow(10,Math.max(r1,r2));
       n=(r1>=r2)?r1:r2;
       return (Math.round(num1*m-num2*m)/m).toFixed(n); //toFixed(n)精确到n位
    }

    //两个浮点数相乘

    function accMul(num1,num2){  //假如(0.01,0.002)
       var m=0,s1=num1.toString(),s2=num2.toString(); 
       try{
           m+=s1.split(".")[1].length //m=0+2=2
          }catch(e){};
       try{
           m+=s2.split(".")[1].length //m=2+3=5
          }catch(e){};
       return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m); //m=5
    }

    // 两个浮点数相除

    function accDiv(num1,num2){
       var t1,t2,r1,r2;
       try{
           t1 = num1.toString().split('.')[1].length;
       }catch(e){
           t1 = 0;
       }
       try{
           t2 = num2.toString().split(".")[1].length;
       }catch(e){
           t2 = 0;
       }
       r1=Number(num1.toString().replace(".",""));//将如0.0001转换为0,0001
       r2=Number(num2.toString().replace(".",""));
       return (r1/r2)*Math.pow(10,t2-t1);
    }
    
   
 
   

猜你喜欢

转载自blog.csdn.net/Web_J/article/details/84866525