javascript浮點運算偏差的成因及解決方法
阿新 • • 發佈:2019-01-28
原文地址:http://eatpockyboy.blog.163.com/blog/static/116734640201231414154243/
最近做javascript算價格總和的時候遇到乘法也有乘不盡的情況。。。= =! 設想是js的運算演算法裡面包含了除法 沒想到是這樣的的 = =! js直譯器的作者們真心強啊。。。 除了下文提及的解決方法之外 還有一個就是如果浮點的小數位確定時 比如價格是小數點後兩位的 那麼我們可以把價格乘以100 運算完之後再作相應的處理 這樣會涉及一個位數過大(比如我這個價格要算個n次方的話就......)而轉字串處理的問題 這樣效率本來就不高的演算法而變得更加笨重 呃 但是下文的通過字串切割分成小數部分和整數部分運算再算結果的這個方法效率貌似也不怎的 因此如何取捨就看諸君的需求了
轉自:http://topic.csdn.net/u/20120329/17/6cc27133-a13f-4b9d-b253-fc8a04fd2f5c.html
-----------------正文-----------------
最近做js是對浮點型別計算時總是有偏差比如
3*0.8輸出2.4000000000000003
在網上查了一下原因:
用解析字串的方式移動小數點,轉化為整數,完畢後,在把小數點復位。
浮點數運算的時候,先轉化為二進位制,用二進位制來算,結果再轉回十進位制
例如 :求1038.1-1000
1038.1=10000001110.0001100110011001100110011001100110011001100.....
1000= 1111101000
1038.1轉化為二進位制是個無限迴圈小數,1100是迴圈節,只能取近似值,誤差就是這裡產生的
如果瀏覽器版本高,可以用toFixed() 方法可把 Number 四捨五入為指定小數位數的數字.
後有固定的 num 位數字。如果必要,該數字會被舍入,也可以用 0 補足,以便它達到指定的長度。如果 num 大於 le+21,則該方法只調用 NumberObject.toString(),返回採用指數計數法表示的字串。
語法
NumberObject.toFixed(num)
返回值
返回 NumberObject 的字串表示,不採用指數計數法,小數點後有固定的 num 位數字。如果必要,該數字會被舍入,也可以用 0 補足,以便它達到指定的長度。如果 num 大於 le+21,則該方法只調用 NumberObject.toString(),返回採用指數計數法表示的字串。
丟擲
當 num 太小或太大時丟擲異常 RangeError。0 ~ 20 之間的值不會引發該異常。有些實現支援更大範圍或更小範圍內的值。
當呼叫該方法的物件不是 Number 時丟擲 TypeError 異常。
在本例中,我們將把數字舍入為僅有一位小數的數字:
Show the number 13.37 with one decimal:
<script type="text/javascript">
var num = new Number(13.37);
document.write (num.toFixed(1))
</script>
輸出:
Show the number 13.37 with one decimal:
13.4
解決方法:
function accMul(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)
}
最近做javascript算價格總和的時候遇到乘法也有乘不盡的情況。。。= =! 設想是js的運算演算法裡面包含了除法 沒想到是這樣的的 = =! js直譯器的作者們真心強啊。。。 除了下文提及的解決方法之外 還有一個就是如果浮點的小數位確定時 比如價格是小數點後兩位的 那麼我們可以把價格乘以100 運算完之後再作相應的處理 這樣會涉及一個位數過大(比如我這個價格要算個n次方的話就......)而轉字串處理的問題 這樣效率本來就不高的演算法而變得更加笨重 呃 但是下文的通過字串切割分成小數部分和整數部分運算再算結果的這個方法效率貌似也不怎的 因此如何取捨就看諸君的需求了
轉自:http://topic.csdn.net/u/20120329/17/6cc27133-a13f-4b9d-b253-fc8a04fd2f5c.html
-----------------正文-----------------
最近做js是對浮點型別計算時總是有偏差比如
3*0.8輸出2.4000000000000003
在網上查了一下原因:
用解析字串的方式移動小數點,轉化為整數,完畢後,在把小數點復位。
浮點數運算的時候,先轉化為二進位制,用二進位制來算,結果再轉回十進位制
例如 :求1038.1-1000
1038.1=10000001110.0001100110011001100110011001100110011001100.....
1000= 1111101000
1038.1轉化為二進位制是個無限迴圈小數,1100是迴圈節,只能取近似值,誤差就是這裡產生的
如果瀏覽器版本高,可以用toFixed() 方法可把 Number 四捨五入為指定小數位數的數字.
後有固定的 num 位數字。如果必要,該數字會被舍入,也可以用 0 補足,以便它達到指定的長度。如果 num 大於 le+21,則該方法只調用 NumberObject.toString(),返回採用指數計數法表示的字串。
語法
NumberObject.toFixed(num)
返回值
返回 NumberObject 的字串表示,不採用指數計數法,小數點後有固定的 num 位數字。如果必要,該數字會被舍入,也可以用 0 補足,以便它達到指定的長度。如果 num 大於 le+21,則該方法只調用 NumberObject.toString(),返回採用指數計數法表示的字串。
丟擲
當 num 太小或太大時丟擲異常 RangeError。0 ~ 20 之間的值不會引發該異常。有些實現支援更大範圍或更小範圍內的值。
當呼叫該方法的物件不是 Number 時丟擲 TypeError 異常。
在本例中,我們將把數字舍入為僅有一位小數的數字:
Show the number 13.37 with one decimal:
<script type="text/javascript">
var num = new Number(13.37);
document.write (num.toFixed(1))
</script>
輸出:
Show the number 13.37 with one decimal:
13.4
解決方法:
function accMul(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)
}