Search code examples
javaroundingbigdecimal

Discrepancy in decimal rounding results


Using Java:

$ jshell
|  Welcome to JShell -- Version 17.0.3
|  For an introduction type: /help intro

Using 'half even' rounding method, 3084.5 rounds to 3084:

jshell> new java.math.BigDecimal("3084.5").setScale(0, java.math.RoundingMode.HALF_EVEN)
$13 ==> 3084

But 3084.51 rounds to 3085:

jshell> new java.math.BigDecimal("3084.51").setScale(0, java.math.RoundingMode.HALF_EVEN)
$13 ==> 3085

Why is the digit 1 affecting the rounding? It's beyond the last significant digit (5) that should be considered during the rounding operation, right?


Solution

  • According to the JavaDoc of RoundingMode.HALF_EVEN:

    Rounding mode to round towards the {@literal "nearest neighbor"} unless both neighbors are equidistant, in which case, round towards the even neighbor.

    That means, with a scale of 0 that you set in the .setScale() (meaning you want 0 decimals):

    • 3084.5 is equidistant from 3084 and 3085, so it will be the even neighbor (hence 3084 that is even, not 3085 that is odd).
    • 3084.51 is not equidistant, it is 0.01 closer to 3085 than 3084, hence it will be the nearest neighbor.