??????? float和double主要為了科學(xué)計算和工程計算而設(shè)計留量,執(zhí)行二進(jìn)制浮點運算窄赋,這是為了在廣泛的數(shù)值范圍上提供較為精確的快速近似計算而精心設(shè)計的。然而楼熄,它們沒有提供完全精確的結(jié)果忆绰,所以不適合用于需要精確結(jié)果的場合,尤其是貨幣計算可岂。
//假設(shè)有1.03元,花掉0.42元后
System.out.println(1.03 - .42);//0.6100000000000001
System.out.println(1.00 - 9 * .10);//0.09999999999999998
使用舍入可以解決上面問題错敢,但并不是所有的問題都能用舍入解決,如有1元,有0.1稚茅,0.2纸淮,0.3,一直到1元的糖果亚享,從0.1開始買咽块,直到不能支付為止:
public static void main(String[] args) {
? ? double funds = 1.00;
? ? int itemsBought = 0;
? ? for(double price = .10; funds >= price; price += .10) {
? ? ? ? ? funds -= price;
? ? ? ? ? itemsBought++;
???? }
???? System.out.println(itemsBought + " items bought.");
????? System.out.println("Money left over: $" + funds);
}
結(jié)果是:
3 items bought.
Money left over: $0.3999999999999999
使用BigDecimal是正確的辦法
public static void main(String[] args) {
???? final BigDecimal TEN_CENTS = new BigDecimal(".10");
???? int itemsBought = 0;
???? BigDecimal funds = new BigDecimal("1.00");
???? for(BigDecimal price = TEN_CENTS; funds.compareTo(price) >= 0; price = price.add(TEN_CENTS)) {
????????? itemsBought++;
????????? funds = funds.subtract(price);
???? }
???? System.out.println(itemsBought + " items bought.");
???? System.out.println("Money left over: $" + funds);
}
結(jié)果是:
4 items bought.
Money left over: $0.00
使用BigDecimal的缺點是:1.與基本類型相比,不方便(需要創(chuàng)建BigDecimal對象)欺税;2.速度慢
使用int或者long侈沪,取決于涉及的數(shù)值大小,同時要自己處理十進(jìn)制小數(shù)晚凿,以分為單位亭罪,而不是以元為單位計算,就可以使用int來處理:
public static void main(String[] args) {
???? int itemsBought = 0;
???? int funds = 100;
???? for(int price = 10; funds >= price; price += 10) {
????????? itemsBought++;
????????? funds -= price;
????? }
???? System.out.println(itemsBought + " items bought.");
???? System.out.println("Money left over: $" + funds);
}
結(jié)果與用BigDecimal是一樣的歼秽。
總結(jié):對于需要精確答案的計算应役,不能使用float或者double,BigDecimal允許完全控制舍入燥筷,如果業(yè)務(wù)要求涉及多種舍入方式箩祥,使用BigDecimal很方便,如果性能很關(guān)鍵荆责,涉及的數(shù)值不大滥比,就可以使用int或者long亚脆,如果數(shù)值范圍沒有超過9位十進(jìn)制數(shù)字做院,可以使用int,如果不超過18位數(shù)字濒持,使用long键耕,如果數(shù)值可能超過18位,就必須用BigDecimal柑营。