一、浮點計算中發生精度丟失
無論你使用的是什么編程語言,在使用浮點型數據進行精確計算時,你都有可能遇到計算結果出錯的情況。
public class FloatTest { public static void main(String[] args) { float f1 = 6.6f; float f2 = 1.3f; System.out.println(f1 + f2); } } ************************************* 結果:7.8999996
二、為何會出現精度丟失
為什么會這樣呢? 因為float和double都是浮點數, 都有取值范圍,都有精度范圍。
計算機只認識0和1,所有類型的計算首先會轉化為二進制的計算。我們demo里的6.6是十進制的,計算機不能直接識別,要先編譯成二進制,在這個過程中發生了精度丟失。
具體請參考:《從計算機二進制角度計算 6.6 + 1.3 的過程》
三、如何使用浮點數進行精確計算
事實上,浮點數並不適合用於精確計算,而適合進行科學計算。這里有一個小知識:既然float和double型用來表示帶有小數點的數,那為什么我們不稱 它們為“小數”或者“實數”,要叫浮點數呢?因為這些數都以科學計數法的形式存儲。當一個數如50.534,轉換成科學計數法的形式為5.053e1,它 的小數點移動到了一個新的位置(即浮動了)。可見,浮點數本來就是用於科學計算的,用來進行精確計算實在太不合適了。
如果是計算金額必須是完全精確的計算, 故不能使用double或者float, 有以下兩個方法:
1.采用java.math.BigDecimal.---參考:《java 中 BigDecimal 詳解》
2.使用int存儲金額的分值,顯示的時候在轉化為元
使用decimal存儲類型的缺點
- 占用存儲空間。浮點類型在存儲同樣范圍的值時,通常比decimal使用更少的空間
- 使用decimal計算效率不高
因為使用decimal時間和空間開銷較大,選用int作為數據庫存儲格式比較合適,可以同時避免浮點存儲計算的不精確和decimal的缺點。對於存儲數值較大或者保留小數較多的數字,數據庫存儲結構可以選擇bigint,可以同時避免浮點存儲計算不精准和DECIMAL精度計算代價高的問題