經過前陣子的忙碌,總算有時間蓋步了,這次要蓋的不是步,而是限量在被發Bug後才知道的Javascript問題。到底是什麼問題呢?問題就是Javascript在進行浮點數運算時底層會發生捨去問題,造成結果預期是整數卻是.99999,例如:123.45 / 100 * 100,答案應該是123.45,但得出來結果竟然是123.44999999999999,不信的話可以打開F12試看看喔。
問題的起因在於Round Error,Round Error就是有關四捨五入這般捨去進位的問題,出現像1/3=0.33333...這種除不盡的問題,就會有誤差,電腦是使用Binary Number來進行數值運算,在遇到除不盡的運算時會自動捨去後面幾位的Binary,再轉成十進位制顯示時就會出現錯誤,通常其他程式語言的DataType來自動處理,但Javascript底層沒有自動解決這問題,所以必須要自己處理。
要在Javascript上解決有幾種方法,最搞剛也最直覺的方式就是每進行一次浮點數運算,就先把有浮點數先轉成整數,然後記錄下該除多少位,經過一連串運算結果轉成整數後,最後在一次除以累積的位數,例如:123.45/100*100 => ((123.45*100)/100*100)/100 = 123.45。
其他方式可以去使用套件,因為這是個Javascript原生的問題,看來也不打算修,所以網路上很多人針對這個議題寫了許多的套件,像,總之撿現成就對了。
例如有個Big.js的Javascript函示庫就可以解決,以下為使用Big.js的範例:
Big.js提供了add(), minus(), mul(), div() 加減乘除的Method可以使用,只要引入big.js後,然後宣告Big的浮點數物件,在使用Big.js提供的Method就可以進行正確的浮點數運算。
參考來源:
What Every Programmer Should Know About Floating-Point Arithmetic
StackOverflow - Is floating point math broken?
StackOverflow - How to multiply in Javascript? problems with decimals
StackOverflow - How to deal with floating point number precision in JavaScript?
Arbitrary-precision arithmetic
問題的起因在於Round Error,Round Error就是有關四捨五入這般捨去進位的問題,出現像1/3=0.33333...這種除不盡的問題,就會有誤差,電腦是使用Binary Number來進行數值運算,在遇到除不盡的運算時會自動捨去後面幾位的Binary,再轉成十進位制顯示時就會出現錯誤,通常其他程式語言的DataType來自動處理,但Javascript底層沒有自動解決這問題,所以必須要自己處理。
要在Javascript上解決有幾種方法,最搞剛也最直覺的方式就是每進行一次浮點數運算,就先把有浮點數先轉成整數,然後記錄下該除多少位,經過一連串運算結果轉成整數後,最後在一次除以累積的位數,例如:123.45/100*100 => ((123.45*100)/100*100)/100 = 123.45。
其他方式可以去使用套件,因為這是個Javascript原生的問題,看來也不打算修,所以網路上很多人針對這個議題寫了許多的套件,像,總之撿現成就對了。
例如有個Big.js的Javascript函示庫就可以解決,以下為使用Big.js的範例:
<!DOCTYPE html> <html> <head> <title>Demo</title> <script src="big.js"></script> <script> var a = new Big(123.45); var b = new Big(100); var c = a.div(b).mul(b); alert(c); </script> </head> <body> </body> </html>
Big.js提供了add(), minus(), mul(), div() 加減乘除的Method可以使用,只要引入big.js後,然後宣告Big的浮點數物件,在使用Big.js提供的Method就可以進行正確的浮點數運算。
參考來源:
What Every Programmer Should Know About Floating-Point Arithmetic
StackOverflow - Is floating point math broken?
StackOverflow - How to multiply in Javascript? problems with decimals
StackOverflow - How to deal with floating point number precision in JavaScript?
Arbitrary-precision arithmetic
留言
張貼留言