Card 05/ 09

ComparisonDifficulty: Intermediate1 min

int, long, double or BigDecimal for an Amount of Money

An invoice line says £19.99. It has a decimal point in it, so double looks like the answer, and double is the answer that produces invoices that are a penny out.

Four ways to hold an amount of money, on exactness, range and effort
TypeExact?RangeCosts you
doubleNo — binary fractions cannot hold 0.1EnormousNothing, until the totals disagree
int of penceYesUp to about £21 millionDividing by 100 everywhere you display it
long of penceYesMore than any real ledger needsThe same division, and a wider field
BigDecimalYes, and it carries its scaleUnboundedAn object per value, and compareTo instead of ==

The decision rule. If the number is money, never use double or float. Use long of the smallest unit when the arithmetic is addition and subtraction and you control both ends. Use BigDecimal when there is division, a tax rate, a currency with a different number of decimal places, or an accountant who will check.

java
BigDecimal price = new BigDecimal("19.99");
BigDecimal vat = price.multiply(new BigDecimal("0.20"));

System.out.println(vat.setScale(2, RoundingMode.HALF_UP));
the string constructor, not the double one — new BigDecimal(19.99) reintroduces the problem
text
4.00

For anything that is not money the rule relaxes: double is the right type for a temperature, a distance or a physics simulation, where being within a fifteenth decimal place is not a defect.