問題
在javascript中整數和浮點數都屬於Number資料型態(簡單資料型別中的一種),我們常發現在印出1.0這樣的浮點數的結果是1而非1.0,這是由於保存浮點數的記憶體空間是儲存整數值的兩倍,所以ECMAScript會不失時機地將浮點數轉換為整數。
上面這種狀況雖然讓強迫症患者有點不舒服,但是好歹也不是什麼大錯,接下來這種情況就很嚇人了。例如我們在計算0.1加0.2時,它的輸出結果不是0.3,而是0.3000000000000004。 what the fuck? !第一次遇到這種狀況的童鞋有沒有感覺到世界觀受到了挑戰?
產生原因
於是趕快翻書來拯救自己的靈魂以及肉體,發現書中赫然寫著:ECMAScrip是基於IEEE754數值浮點計算如果不知道IEEE754是什麼就點我吧,這種數值計算方法會將數值儲存為二進位然後進行計算,由於浮點數用二進位表達時是無窮的,所以在進行算術計算時會產生捨入誤差,由於捨入誤差的存在,浮點數計算的精確度遠不如整數計算,最後記住了永遠不要測試某個特定浮點數的數值。
所以楊綛先生說的對,年輕人就是想的多讀書少,沒文化總是動不動就會懷疑人生,所以還是要多讀書啊! ! !
解決方案
所謂對症下藥,知道了問題產生的原因那麼就可以找到問題的解決方案啦。既然是因為浮點數的二元為無窮數所產生的誤差,這種誤差在整數運算中不會存在,那麼聰明的你是不是窺破真相了呢?沒錯,那就是在運算工程中將浮點數轉換為整數,再將得出的結果轉換為浮點數。客官,以下是新鮮上的代碼~
//加法 function FloatAdd(arg1,arg2){ var r1,r2,m; try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0; //参数1为整数}; //参数1小数点后的位数 try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0; //参数2为整数}; //参数2小数点后的位数 m=Math.pow(10,Math.max(r1,r2)); //取其中较大的位数 return (arg1*m+arg2*m)/m; //先将arg1和arg2转换为整数进行计算,然后再转换回浮点数 }