javaroundingnumericbigdecimal

Why does RoundingMode.HALF_EVEN in BigDecimal division round 0.454 to 0.5?


The rounding mode HALF_EVEN is supposed to round a (decimal) number ending in 5 to the closest even less precise number (e.g., 4.5 is rounded to 4, whereas 5.5 is rounded to 6).

Now, it seems that Java's division of BigDecimal is not obeying that rule; the following code gets it to round 0.45 to 0.5:

import java.math.*;

class Round {
    public static void main(String[] args) {
        BigDecimal five = BigDecimal.valueOf(5);
        BigDecimal eleven = BigDecimal.valueOf(11);
        BigDecimal x = five.divide(eleven, 1, RoundingMode.HALF_EVEN);
        System.out.println(x);
    }
}

Output 0.5 Note that 5/11 = 0.4545454545... so when looking at the first two digits after the decimal point, 0.45, we clearly would want to see that rounded to the nearest even neighbor, i.e. to 0.40, not 0.50.

Can anyone explain this?

(In case it matters, I'm running java -version = openjdk version "11.0.15" 2022-04-19)

Note:

  1. This is not about rounding before getting a value into the BigDecimal; indeed the result is unchanged when using the string constructor
     BigDecimal five = new BigDecimal("5");
     BigDecimal eleven = new BigDecimal("11");
     BigDecimal x = five.divide(eleven, 1, RoundingMode.HALF_EVEN);
  1. It also doesn't depend on the scale at which we round (as long as scale is odd), and you can scale the number up (e.g., round 500/11).

Solution

  • HALF_EVEN:

    round towards the "nearest neighbor" unless both neighbors are equidistant, in which case, round towards the even neighbor.

    So it is needed to first decide whether both neighbours are equidistant.

    so when looking at the first two digits after the decimal point...

    That's not sufficient to determine whether the value is equidistant is equidistant to both neighbours, which in this case is 0.4 and 0.5. We need to look at one more digit in this case.

    In the case of 5/11, 5/11 is closer to 0.5 (distance = 0.045454545...) than to 0.4 (distance = 0.0545454...), so "round towards the even neighbor" is not applied, and "round towards the 'nearest neighbor'" is.