Effective Java 之-----精确的答案与double&float

题目: 假设你口袋里有1$,看到货架上有一排美味的糖果,标价分别为0.10$,0.20$,0.30$...1$,你打算从标价为0.10$的糖果开始买起,每种买一颗,一直到不能支付货架上下一种价格的糖果为止,那么可以买多少颗糖果?还可以找回多少零钱?

使用double的程序如下:

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("change:$"+funds);

返回结果如下:
3 items bought.
change:$0.3999999999999999

这个答案是不正确的,解决方案是使用BigDecimal,int或者long进行货币计算

使用BigDecimal的程序如下:

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("change:$"+funds);

返回结果如下:
4 items bought.
change:$0

这个结果是正确的。

使用int的程序如下(需将1.00$先转换为100cents):

int itemsBought = 0;
int funds = 100;
for(int price=10;funds>=price;price+=10){
      funds -= price;
      itemsBought++;
}
System.out.println(itemsBought+" items bought.");
System.out.println("change:$"+funds);

返回结果如下:
4 items bought.
change:$0

这个结果也是正确的。

所以:
1)如果需要通过法定要求的舍入行为进行业务计算,使用BigDecimal是非常方便的;
2)如果性能非常关键,而且又不介意记录十进制小数点,而且所涉及的数值又不太大,就可以使用int或long,
3) 如果数值范围没超过9位十进制数字,就可以使用int,如果数值范围没超过18位十进制数字,可以使用long,如果数值范围超过了18位十进制数字,就必须使用BigDecimal。

原文地址:https://www.cnblogs.com/hunterCecil/p/5614924.html