

運作結果:
奇怪了,為什麼10-9.6輸出結果不是0.4呢?
這是因為浮點數特性所決定的,它有可能(注意是有可能)是不準确的,而是無限接近準确值,但不能完全準确。至于它為什麼會有這個特性,這是由于浮點數的存儲規則所決定的,具體啥,就不深究了。
0.4這個十進制小數如何轉換成二進制的小數,使用"乘2取整,順序排列"法(不懂,這就沒招了,太基礎了.....),我們發現0.4不能使用二進制準确的表示,在二進制數的世界裡它是一個無限循環的小數,也就是說,"展示"都不能"展示",更别說在記憶體中存儲了.
浮點數的存儲包括三部分:符号位,指數位,尾數.具體不在介紹.
可以這樣了解,在十進制的世界裡沒有辦法準确表示1/3,那在二進制世界裡當然也無法準确表示1/5,在二進制的世界裡1/5是一個無限循環的小數.
知道小數是如何轉換為二進制就OK了,比如0.5,我們知道它的二進制數是:0.1;而0.4轉換為二進制就難了, 是個無限循環的東東,
0.0110 0110 0110 ……(0110為循環節)。而計算機它隻認識0和1,即0.4在轉換時就失真了, 可想而知,輸出結果多了一段小尾巴也不足為奇了,它隻是為了達到無限接近準确值這個原則而已。
以後遇到這種對資料精度要求比較嚴格的資料處理時,我們應該如何去避免這類問題的發生?
對結果取整不就對了嗎?


運作結果:列印出0.4
看似解決了問題,但是隐藏了一個很深的問題,金融行業的計算方法,會計系統一般記錄小數點後的4位小數,但是在彙總,展現,報表中,則隻記錄小數點後的2位小數,如果使用浮點數來計算貨币,想想看,在大批量的加減乘除後結果會有多大的差距.
會計系統要的就是準确.解決這個問題有兩種方案:
第一種方案:
先乘以10的n次方化成整數參與運算,計算後,再除以10的n次方縮小回去。
這樣處理是計算簡單,準确,在 一般的非金融行業(如零售行業)應用比較多,此方法還會應用于某些POS機,它們的輸入和輸出全部是整數,那運算就更簡單.
第二種方案:
我們應該想到java師祖們早已發現這個問題,并為我們提供類來解決這類問題,它就是BigDecimal類
BigDecimal是專門為彌補浮點數無法精确計算的缺憾而設計的類.而且它本身也提供了加減乘除的常用數學算法,特别是與資料庫Decimal類型的字段映射時,BigDecimal是最優的解決方案.
本文轉自SummerChill部落格園部落格,原文連結:http://www.cnblogs.com/DreamDrive/p/5424825.html,如需轉載請自行聯系原作者