Card 05/ 09
int vs long vs double vs BigDecimal for Money
£19.99 has a decimal point, so double looks right, and double is the type that makes invoices a penny out.
Money needs a type that stores amounts exactly. double does not, so the choice is between a whole number of pence in an int or a long, and BigDecimal, a class that stores decimal numbers exactly and carries its own number of decimal places.
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 a penny out.
| Type | Exact? | Range | Costs you |
|---|---|---|---|
double | No: binary fractions cannot hold 0.1 | Enormous | Nothing, until the totals disagree |
int of pence | Yes | Up to about £21 million | Dividing by 100 everywhere you display it |
long of pence | Yes | More than any real ledger needs | The same division, and a wider field |
BigDecimal | Yes, and it carries its scale | Unbounded | An 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.
BigDecimal price = new BigDecimal("19.99");
BigDecimal vat = price.multiply(new BigDecimal("0.20"));
System.out.println(vat.setScale(2, RoundingMode.HALF_UP));4.00For 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.
← → move through sections and cards