3

I stumbled across following scenario where how rounding works does not make sense to me.

new BigDecimal(9999.005).setScale(2, RoundingMode.HALF_UP) -- 9999.0
new BigDecimal(999.005).setScale(2, RoundingMode.HALF_UP) -- 999.0
new BigDecimal(9.005).setScale(2, RoundingMode.HALF_UP) -- 9.01
Math.round(9999.005*100.00)/100.000 -- 9999.0
Math.round(999.005*100.00)/100.000 -- 999.01
Math.round(9.005*100.00)/100.000 -- 9.01

My understanding is when RoundingMode.HALF_UP is used, it should convert all three values .01 regardless of what is the number before decimal.

Java documentation - Rounding mode to round towards {@literal "nearest neighbor"} * unless both neighbors are equidistant, in which case round up. * Behaves as for {@code RoundingMode.UP} if the discarded * fraction is ≥ 0.5; otherwise, behaves as for * {@code RoundingMode.DOWN}. Note that this is the rounding * mode commonly taught at school.

Am I wrong in the understanding on how this should work?

  • 2
    try printing `new BigDecimal(9999.005).toString()`; or use `new BigDecimal("9999.005")` in your tests - floating point numbers like `double` and `float` (often) are just approximations) (and this kind of question is not exactly new on this site) – user16320675 Aug 04 '22 at 14:01
  • 1
    Does this answer your question? [How to round 0.745 to 0.75 using BigDecimal.ROUND\_HALF\_UP?](https://stackoverflow.com/questions/12460482/how-to-round-0-745-to-0-75-using-bigdecimal-round-half-up) Specifically use a string conversion `new BigDecimal("9999.005")` or use the valueOf method to retain precision of the double `new BigDecimal.valueOf(9999.005)` – sorifiend Aug 04 '22 at 14:05
  • You both are right. Never knew floats and doubles loses precision. I tried the string values and they round up as expected. – user2769607 Aug 04 '22 at 14:17
  • 1
    basically `9999.005` cannot be expressed precisely as `double` (like we cannot write 1/3 precisely as a floating point - needs infinite digits) – user16320675 Aug 04 '22 at 14:30

0 Answers0