float和double类型主要是为了科学计算和工程计算而设计的。它们执行二进制浮点运算,这是为了在广泛的数值范围上提供较为精确的快速近似计算而精心设计的。它们并没有提供完全精确的结果。
float和double尤其不适合用于货币计算,因为要让一个float获取double精确的表示0.1是不可能的
System.out.println(1.03-0.42);
//结果0.6100000000000001
double funds=1.00;
int itemsBought=0;
for(double price=0.1;funds>=price;price+=0.1){
funds-=price;
itemsBought++;
}
System.out.println("itemsBought="+itemsBought+";change="+funds);
//结果itemsBought=3;change=0.3999999999999999
解决这个问题的办法是使用BigDecimal、int或者long进行货币计算
final BigDecimal TEN_CENTS=new BigDecimal("0.1");
int itemsBought=0;
BigDecimal funds=new BigDecimal("1.0");
for(BigDecimal price=TEN_CENTS;funds.compareTo(price)>=0;price=price.add(TEN_CENTS)){
itemsBought++;
funds=funds.subtract(price);
}
System.out.println("itemsBought="+itemsBought+";change="+funds);
//结果itemsBought=4;change=0.0
但是使用BigDecimal有两个缺点:很不方便而且速度慢
当然也可以使用int或long,最明显的做法就是以分为单位进行计算而不是元
//effective java总结