BigDecimal and money

Core Java · lesson 33 of 42 · 4 min read

See why double loses cents, and hold money in BigDecimal or in whole cents instead.

Open this lesson in the learning hub

Key points

  • double holds binary fractions, and 0.1 has no exact binary form, so 0.1 + 0.2 drifts.
  • Never hold money in double or float. Use BigDecimal, or count whole cents in a long.
  • Always build it from a String. new BigDecimal(0.1) copies the binary error straight in.
  • It is immutable: add and multiply return a new value, so ignoring the result does nothing at all.
  • divide throws unless the result terminates. Pass a scale and a RoundingMode, usually HALF_UP.
  • equals compares the scale, so 1.0 is not 1.00. Compare values with compareTo(x) == 0.

Example

import java.math.BigDecimal;
import java.math.RoundingMode;

public class Main {
    public static void main(String[] args) {
        System.out.println("double     : 0.1 + 0.2   = " + (0.1 + 0.2));
        System.out.println("double     : 1.03 - 0.42 = " + (1.03 - 0.42));

        BigDecimal a = new BigDecimal("0.1");
        BigDecimal b = new BigDecimal("0.2");
        System.out.println("BigDecimal : 0.1 + 0.2   = " + a.add(b));

        System.out.println("new BigDecimal(0.1) is the trap:");
        System.out.println("  " + new BigDecimal(0.1));
        System.out.println("  BigDecimal.valueOf(0.1) = " + BigDecimal.valueOf(0.1));

        BigDecimal price = new BigDecimal("19.99");
        BigDecimal total = price.multiply(new BigDecimal("3"));
        System.out.println("19.99 x 3 = " + total + " with scale " + total.scale());
        System.out.println("as money  = " + total.setScale(2, RoundingMode.HALF_UP));

        BigDecimal third = BigDecimal.ONE.divide(new BigDecimal("3"), 5, RoundingMode.HALF_UP);
        System.out.println("1 / 3 needs a scale: " + third);

        BigDecimal x = new BigDecimal("1.0");
        BigDecimal y = new BigDecimal("1.00");
        System.out.println("equals sees the scale: " + x.equals(y) + ", compareTo == 0: " + (x.compareTo(y) == 0));

        long cents = 1999L * 3;
        System.out.println("or just count cents  : " + cents + " -> " + (cents / 100) + "." + (cents % 100));
    }
}

Money is decimal: build BigDecimal from a String, or count cents in a long.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Core Java course, and every lesson in it is listed on the Core Java contents page.