代码改变世界

Effective Java 48 Avoid float and double if exact answers are required

2014-04-11 14:49  小郝(Kaibo Hao)  阅读(387)  评论(0编辑  收藏  举报

Reason

The float and double types are particularly ill-suited for monetary calculations because it is impossible to represent 0.1 (or any other negative power of ten) as a float or double exactly.

   

// This will print 0.6100000000000001

System.out.println(1.03 - .42);

   

// This will print 0.09999999999999998

System.out.println(1.00 - 9 * .10);

   

Right way

Use BigDecimal , int , or long for monetary calculations

   

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);

}

   

Advantage

  1. Precise
  2. Full control over Rounding(Able to select from eight rounding modes whenever an operation that entails rounding is performed)

Disadvantage

  1. less convenient than using a primitive arithmetic type
  2. It's slower

   

An alternative to using BigDecimal

Using int or long, depending on the amounts involved, and to keep track of the decimal point yourself.

   

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 + " cents");

}

   

Decision on choosing implementation

Quantities

9

18

>18

Use

int

long

BigDecimal

   

Summary

Don't use float or double for any calculations that require an exact answer. Use BigDecimal if you want the system to keep track of the decimal point and you don't mind the inconvenience and cost of not using a primitive type.