浮點數在金額計算中的使用總結
阿新 • • 發佈:2019-03-11
class effect sta void java 解決 clas sel 成了
浮點數在金額計算中的使用總結(摘自~~)
double 和 float 類型的變量不適合用作金額計算是java語言使用中的基本知識,但在實際應用中此基本常識經常被程序員忽視,想當然的用在了實際的金額計算場景中,造成難以察覺的錯誤。在此對金額計算的使用方法做個總結,以規範後續使用。
1. double和float 的不準確
《effective Java》中指出,float和double類型主要是為科學計算和工程計算而設計的,不應該被用於需要精確結果的場合,尤其不適合於貨幣計算,見如下代碼:
public class DoubleHandle {
static double a = 2.0;
static double b = 1.1;
public static void main(String[] args){
System.out.print("2.0 減 1.1 的double類型計算值為:");
System.out.println((a - b));
}
}
輸出結果為
2.0 減 1.1 的double類型計算值為:0.8999999999999999
明顯可見結果是不正確的。原因為在二進制系統中無法精確的表示10的負n次冪,如同十進制無法精確的表示1/3一樣。為了能夠解決這個問題,java提供了BigDecimal類,那麽只要使用了BigDecimal類結果就一定正確嗎?
2. BigDecimal類的錯誤使用
根據上文結論,容易犯的錯誤如下圖代碼:
public class DoubleHandle {
static BigDecimal aBig = new BigDecimal(2.0);
static BigDecimal bBig = new BigDecimal(1.1);
public static void main(String[] args){
System.out.println("2.0 減 1.1 的BigDecimal類型計算值為:"
+ String.valueOf(aBig.subtract(bBig)));
}
}
運行結果為:
2.0 減 1.1 的BigDecimal類型計算值為:
0.899999999999999911182158029987476766109466552734375
結果仍然是錯誤的。原因為實例化BigDecimal類時,使用的是double類型的常量,那麽仍然無法避免double類型精度丟失的問題,正確的使用方式為用String類型來初始化BigDecimal類。
3. BigDecimal的正確使用
使用下面的代碼運行:
public class DoubleHandle {
static BigDecimal aStrBig = new BigDecimal("2.0");
static BigDecimal bStrBig = new BigDecimal("1.1");
public static void main(String[] args){
System.out.println("2.0 減 1.1 的BigDecimal類型計算值為:"
+ String.valueOf(aStrBig.subtract(bStrBig)));
}
}
運行結果為:
2.0 減 1.1 的BigDecimal類型計算值為:0.9
可見已為正確的結果。
4. BigDecimal的使用註意
BigDecimal沒有定義 +或 * 等操作符的重載,因此加法等操作要用方法來實現。需要註意的是BigDecimal在執行了運行操作後,結果值並不會覆蓋回原操作數,而是生成了新的結果值。見如下代碼:
public class DoubleHandle {
static BigDecimal aStrBig = new BigDecimal("2.0");
static BigDecimal bStrBig = new BigDecimal("1.1");
public static void main(String[] args){
System.out.println("2.0 減 1.1 的BigDecimal類型計算值為:"
+ String.valueOf(aStrBig.subtract(bStrBig)));
System.out.println("aStrBig值為:" + String.valueOf(aStrBig));
}
}
運行結果為:
2.0 減 1.1 的BigDecimal類型計算值為:0.9
aStrBig值為:2.0
可見計算結果0.9並沒有保存到aStrBig中去,僅僅輸出打印後就拋棄了。原因為BigDecimal為不可變類,我們不能修改現有實例的值,對這些類型的操作將返回新的實例,因此運算生成的結果值需要定義新的變量來保存。
浮點數在金額計算中的使用總結