JavaScript浮點數運算 -- 精度問題

 

JavaScript小數在做四則運算時,精度會丟失,這會在項目中引起諸多不便,先請看下面腳本:

Js代碼 複製代碼
  1. <script type="text/javascript" language="javascript">      
  2.     alert(1/3);//彈出: 0.3333333333333333   
  3.     alert(0.09999999 + 0.00000001);//彈出: 0.09999999999999999    
  4.     alert(-0.09999999 - 0.00000001);//彈出: -0.09999999999999999   
  5.     alert(0.012345 * 0.000001);//彈出: 1.2344999999999999e-8   
  6.     alert(0.000001 / 0.0001);//彈出: 0.009999999999999998   
  7. </script>    

   按正常計算的話,除第一行外(因爲其本身就不能除盡),其他都應該要得到精確的結果,從彈出的結果我們卻發現不是我們想要的正確結果。爲了解決浮點數運算不準確的問題,在運算前我們把參加運算的數先升級(10的X的次方)到整數,等運算完後再降級(0.1的X的次方)。現收集並整理貼於此,以備後用。

  • 加法

Js代碼 複製代碼
  1. //說明:javascript的加法結果會有誤差,在兩個浮點數相加的時候會比較明顯。這個函數返回較爲精確的加法結果。   
  2. //調用:accAdd(arg1,arg2)   
  3. //返回值:arg1加上arg2的精確結果   
  4. function accAdd(arg1,arg2){   
  5.     var r1,r2,m;   
  6.     try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0}   
  7.     try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0}   
  8.     m=Math.pow(10,Math.max(r1,r2))   
  9.     return (arg1*m+arg2*m)/m   
  10. }   
  11.   
  12. //給Number類型增加一個add方法,調用起來更加方便。   
  13. Number.prototype.add = function (arg){   
  14.     return accAdd(arg,this);   
  15. }  
  • 減法

Js代碼 複製代碼
  1. //說明:javascript的減法結果會有誤差,在兩個浮點數相加的時候會比較明顯。這個函數返回較爲精確的減法結果。   
  2. //調用:accSub(arg1,arg2)   
  3. //返回值:arg1減上arg2的精確結果   
  4. function accSub(arg1,arg2){       
  5.     return accAdd(arg1,-arg2);   
  6. }   
  7.   
  8. //給Number類型增加一個sub方法,調用起來更加方便。   
  9. Number.prototype.sub = function (arg){   
  10.     return accSub(this,arg);   
  11. }  
  •  乘法

Js代碼 複製代碼
  1. //說明:javascript的乘法結果會有誤差,在兩個浮點數相乘的時候會比較明顯。這個函數返回較爲精確的乘法結果。   
  2. //調用:accMul(arg1,arg2)   
  3. //返回值:arg1乘以arg2的精確結果   
  4. function accMul(arg1,arg2)   
  5. {   
  6.     var m=0,s1=arg1.toString(),s2=arg2.toString();   
  7.     try{m+=s1.split(".")[1].length}catch(e){}   
  8.     try{m+=s2.split(".")[1].length}catch(e){}   
  9.     return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m)   
  10. }   
  11.   
  12. //給Number類型增加一個mul方法,調用起來更加方便。   
  13. Number.prototype.mul = function (arg){   
  14.     return accMul(arg, this);   
  15. }  
  •  除法

Js代碼 複製代碼
  1. //說明:javascript的除法結果會有誤差,在兩個浮點數相除的時候會比較明顯。這個函數返回較爲精確的除法結果。   
  2. //調用:accDiv(arg1,arg2)   
  3. //返回值:arg1除以arg2的精確結果   
  4. function accDiv(arg1,arg2){   
  5.     var t1=0,t2=0,r1,r2;   
  6.     try{t1=arg1.toString().split(".")[1].length}catch(e){}   
  7.     try{t2=arg2.toString().split(".")[1].length}catch(e){}   
  8.     with(Math){   
  9.         r1=Number(arg1.toString().replace(".",""))   
  10.         r2=Number(arg2.toString().replace(".",""))   
  11.         return (r1/r2)*pow(10,t2-t1);   
  12.     }   
  13. }   
  14.   
  15. //給Number類型增加一個div方法,調用起來更加方便。   
  16. Number.prototype.div = function (arg){   
  17.     return accDiv(this, arg);   
  18. }  

 

測試一把

Js代碼 複製代碼
  1. <script type="text/javascript" language="javascript">   
  2.   
  3.     /*  
  4.      alert(0.09999999 + 0.00000001);//彈出: 0.09999999999999999  
  5.      alert(-0.09999999 - 0.00000001);//彈出: -0.09999999999999999  
  6.      alert(0.012345 * 0.000001);//彈出: 1.2344999999999999e-8  
  7.      alert(0.000001 / 0.0001);//彈出: 0.009999999999999998  
  8.     */  
  9.     alert(0.09999999.add(0.00000001));//彈出: 0.1   
  10.     alert(-0.09999999.sub(0.00000001));//彈出: -0.09999998     
  11.     alert(0.012345.mul(0.000001));//彈出: 1.2345e-8   
  12.     alert(0.000001.div(0.0001));//彈出: 0.01   
  13.   
  14. </script>  

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章