Precision and scale in BigDecimal and MathContext

Lately, after publishing the previous post, a friend of mine passed me a snipped of BigDecimal code. He was wondering, why the following execution:

BigDecimal a = new BigDecimal(2.9);
BigDecimal b = new BigDecimal(4000);

MathContext mc = new MathContext(2, RoundingMode.HALF_DOWN);
BigDecimal r1 = a.multiply(b, mc);
BigDecimal r2 = a.multiply(b).setScale(2, RoundingMode.HALF_DOWN);

System.out.println("r1 = " + r1);
System.out.println("r2 = " + r2);

is returning different values for r1 and r2:

r1 = 1.2E+4
r2 = 11600.00

Well, at first glance it seems that r1 differs from r2 in only one thing: the r1 is using RoundingMode through MathContext object, while the r2 is using the RoundingMode through setScale(-) method.

But when you look at the JavaDocs, you’ll find that the MathContext constructor is accepting not a scale argument but a precision one:

MathContext(int setPrecision, RoundingMode setRoundingMode)

Therefore, creating a MathContext object as follows:

MathContext mc = new MathContext(2, RoundingMode.HALF_DOWN);

defines a MathContext object with precision value set to 2.

So, the below operation:

MathContext mc = new MathContext(2, RoundingMode.HALF_DOWN);
BigDecimal r1 = a.multiply(b, mc);

is actually doing following things:

So, the most important lesson from this case is to read JavaDocs carefully and if you’re not sure – read it once again ;-)