出現這種結果的原因:float和double類型尤其不適合用於貨幣運算,因為要讓一個float或double精確的表示0.1或者任何其他負數次方值是不可能的(十進制系統中不能准確的表示出1/3,同樣二進制系統也不能准確的表示1/10)。
1.十進制整數轉為二進制數:
例子:11表示成二進制數:
11/2 =5 余1
5/2 = 2 余1
2/2 = 1 余0
1/2 = 0 余1
0結束,11二進制表示為(從下往上):1011
注意:只要遇到除以后的結果為0就結束了。所有的整數除以2一定能夠最終得到0,但是小數就不能,小數轉變為二進制的算法就有可能會無限循環下去。
2.十進制小數轉為二進制數
算法是乘以2知道沒有了小數為止,例子:
0.9表示成二進制數:
0.9*2 = 1.8 取整數部分:1
0.8*2 = 1.6 取整數部分:1
0.6*2 = 1.2 取整數:1
0.2*2 = 0.4 取整數:0
0.4*2 = 0.8 取整數:0
0.8*2 = 1.6 取整數:1
。。。。
0.9二進制表示為(從上往下):1100100100100.......
注意:上面的計算過程循環了,也就是說乘以2永遠不能消滅小數部分,這樣算法將無限下去。顯然,小數的二進制表示有時是不能精確的。道理很簡單,十進制系統中不能准確的表示出1/3,同樣二進制也無法准確的表示1/10。這也是浮點型出現精度丟失問題的主要原因。
解決方案一:
如果不介意記錄十進制的小數點,而且數值不大,那么可以使用long,int等基本類型,
int resultInt = 10 -9;
double result = (double)resultInt / 100;//自己控制小數點
解決方案二:
使用BigDecimal,而且需要在構造參數使用String類型.
float和double只能用來做科學計算或者工程計算,在商業計算等精確計算中,要用java.math.BigDecimal。
在《EffectiveJava》這本書中就給出了一個解決方法。該書中也指出,float和double只能用來做科學計算或者是工程計算,在商業計算等精確計算中,我們要用java.math.BigDecimal。
BigDecimal類一個有4個方法,我們只關心對我們解決浮點型數據進行精確計算有用的方法,即
BigDecimal(double value) // 將double型數據轉換成BigDecimal型數據
原理:

