Tuesday, August 25, 2009

Should I use BigDecimal or Double?

Here's something to keep in mind using doubles and BigDecimals. When you do this:
System.out.println(new BigDecimal(0.1));

You get this:
0.1000000000000000055511151231257827021181583404541015625

Pretty weird hey!

The javadoc explains what is going on, but I'll attempt to summarise it.

Basically, The weirdness is not with BigDecimal, it is with double. Doubles cannot accurately represent most decimal fractions.

Why? Because a double by definition is a representation of a number that can be stored in 64 bits of data. If we want to store a number, the only way the computer can remember it is by setting 64 individual bits to either 1 or 0. This is fine for most whole numbers.

However if we want to store a decimal fraction like 0.1 - it simply cannot be done in 64 binary bits of data. Binary land doesn't really know anything about decimal land. It's like an inhabitant of Lineland trying to understand the world of Flatland.

So to save our requested 0.1 double, the computer frantically flips those 64 ones and zeros until it gets something that is as close as possible to 0.1 - which as it turns out is 0.1000000000000000055511151231257827021181583404541015625.

Then, when we use that double in BigDecimal's constructor - BigDecimal does an "exact conversion", and uses the number that is literally represented by those 64 bits.

To summarise, if you care about the precision of your decimal fractions (eg. for storing currency), you should definitely be using BigDecimal. You should only be looking to use double if you know exactly why you need it.

0 comments: