The float and double
types
are particularly illsuited for monetary calculations because it is
impossible to represent 0.1 (or any other negative power of ten) as a float or double
exactly.
For example, suppose you have $1.03 in your pocket, and you spend 42¢. How much
money do you have left? Here’s a naive program fragment that attempts to answer
this question:
System.out.println(1.03 - .42);
Unfortunately,
it prints out 0.6100000000000001. This is not
an isolated case. Suppose you have a dollar in your pocket, and you buy nine
washers priced at ten cents each. How much change do you get?
System.out.println(1.00 - 9 * .10);
According to
this program fragment, you get $0.09999999999999998.
You might
think that the problem could be solved merely by rounding results prior to
printing, but unfortunately this does not always work.
The right way
to solve this problem is to use BigDecimal, int, or long
for
monetary calculations.
There are,
however, two disadvantages to using BigDecimal: it’s less
convenient than using a primitive arithmetic type, and it’s slower. The latter
disadvantage is irrelevant if you’re solving a single short problem, but the
former may annoy you.
An alternative
to using BigDecimal is to use int or long, depending on
the amounts involved, and to keep track of the decimal point yourself.
In 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. Using BigDecimal has the added advantage that it gives you
full control over rounding, letting you select from eight rounding modes
whenever an operation that entails rounding is performed. This comes in handy
if you’re performing business calculations with legally mandated rounding
behavior. If performance is
of the
essence, you don’t mind keeping track of the decimal point yourself, and the
quantities aren’t too big, use int or long. If the quantities don’t exceed nine decimal
digits, you can use int; if they don’t exceed eighteen
digits, you can use long. If the quantities might exceed
eighteen digits, you must use BigDecimal.
Reference: Effective Java 2nd Edition by Joshua Bloch