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:
- multiple the
a
value (2.9) byb
value (4000) which results in 11600, - set the precision to given value (2) which results in 11[.600],
- round this value using given RoundingMode HALF_DOWN, which gives you the value of 12000 (1.2E+4).
So, the most important lesson from this case is to read JavaDocs carefully and if you’re not sure – read it once again ;-)