0

Why does BigDecimal divide cause rounding to happen even though the value should fit comfortably in 4 significant digits?

BigDecimal realPercent = new BigDecimal(1.25, new MathContext(4));
// 1.25
BigDecimal percentDivider = new BigDecimal(100, new MathContext(4));
realPercent = realPercent.divide(percentDivider, BigDecimal.ROUND_HALF_UP);
// 0.01

It's possible to make divide behave like I want by setting the precision on the method call, but it doesn't explain why it doesn't already do it.

realPercent.divide(percentDivider, 4, BigDecimal.ROUND_HALF_UP)
// 0.0125
Kit Sunde
  • 35,972
  • 25
  • 125
  • 179

2 Answers2

2

From the Javadoc of divide(BigDecimal, RoundingMode):

Returns a BigDecimal whose value is (this / divisor), and whose scale is this.scale()

The last part is important - the scale of your initial value is 2 (the unscaled value is 125). Because you've called an overload that pins the scale, the closest result available is scale=2, unscaled=1, i.e. 0.01.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Ah. I was under the impression that the `MathContext` would set the scale (not true!). You're right, if I `realPercent.setScale(4)` after creating the first `BigDecimal` then doing `realPercent.divide(percentDivider, BigDecimal.ROUND_HALF_UP)` it will divide on the scale I was expecting. Cool. – Kit Sunde May 15 '17 at 10:02
1

By explicitly setting the rounding mode in your divide call here:

realPercent = realPercent.divide(percentDivider, BigDecimal.ROUND_HALF_UP);

you override the used MathContext. If you specify the MathContext with rounding mode right away, it works as expected:

BigDecimal realPercent = new BigDecimal(1.25, new MathContext(4, RoundingMode.HALF_UP));
// 1.25
BigDecimal percentDivider = new BigDecimal(100, new MathContext(4, RoundingMode.HALF_UP));
realPercent = realPercent.divide(percentDivider);
//0.0125
Hendrik
  • 5,085
  • 24
  • 56