1. 程式人生 > >JS浮點數精度缺失問題

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);
    }