Search code examples
javabigdecimal

How do I calculate correctly with Java’s BigDecimal?


As I understood it, BigDecimal is there for properly dealing with numbers with fixed decimal places (i.e. money). Here is a little program I wrote:

import java.math.*;

public class Main {
    public static void main(String[] args) {
        BigDecimal a = new BigDecimal(11.22, new MathContext(2, RoundingMode.HALF_UP));
        System.out.println("a: " + a);
        BigDecimal b = a.add(new BigDecimal(0.04));
        System.out.println("b: " + b);
    }
}

I expected to see:

a: 11.22
b: 11.26

But what I got is:

a: 11
b: 11.040000000000000000832667268468867405317723751068115234375

I set a to have two decimal places, but it both does not print them, and it even forgets them and rounds to plain int. Why? b should add 0.04 and know from a to have two decimal places, too. This was at least what I expected.

How is this solved correctly using BigDecimal edit: with two double values as input and a known number of decimal places? [I.e., because an API does not give me anything else than these two doubles.] (I know there are other ways to reliably calculate with money (starting from calculating in cents with int), but that’s out of the scope of my question.)


Solution

  • As @Progman also wrote, using the double constructor will create an exact decimal representation of the double value, and it is advised against in the documentation.

    However the reason you are getting 11 instead of 11.22 is that you have set the precision of your MathContext to 2.
    Precision is the number of digits used and not the number of decimal places. So if you changed your code to use 4 as the precision, then you would get the output

    a: 11.22
    b: 11.260000000000000000832667268468867405317723751068115234375
    

    Still with the problem of the double value being used, but now with more decimal places!

    The definition of the precision as the number of digits is in the MathContext class documentationdocumentation