When I ROUND_HALF_UP 10.12445 with scale 2, I expect to get 10.13, because 10.12445 -> 10.1245 -> 10.125 -> 10.13 But the result is 10.12
BigDecimal b = new BigDecimal("10.12445"); b = b.setScale(2, BigDecimal.ROUND_HALF_UP); System.out.println("10.12445 scale 2 : " + b); // 10.12
Therfore if I succesively round with scales 4, 3 and 2, I get the result that I expect:
BigDecimal a = new BigDecimal("10.12445"); a = a.setScale(4, BigDecimal.ROUND_HALF_UP); System.out.println("10.12445 scale 4 : " + a); //10.1245 a = a.setScale(3, BigDecimal.ROUND_HALF_UP); System.out.println("10.1245 scale 3 : " + a); //10.125 a = a.setScale(2, BigDecimal.ROUND_HALF_UP); System.out.println("10.125 scale 2 : " + a); //10.13
Did I miss something?
Is there a way to get the result I expect directly?
Advertisement
Answer
Rounding mode to round towards “nearest neighbor” unless both neighbors are equidistant, in which case round up. Behaves as for
RoundingMode.UP
if the discarded fraction is ≥ 0.5; otherwise, behaves as forRoundingMode.DOWN
.
This rounding mode rounds towards the nearest neighbour, and only if the neighbours are equally near do we do something different. For the scale 2, the neighbours of 10.12445 are 10.12 and 10.13. Which is nearer? Are they equally near?
10.13 - 10.12445 = 0.00555 10.12445 - 10.12 = 0.00445
Clearly 10.12 is nearer, so that is the result.
The sort of rounding that you are looking for seems to be applying HALF_UP
repeatedly, rounding one decimal place at a time, until the scale is 2:
var number = new BigDecimal("10.12445"); for (int i = number.scale() ; i >= 2 ; i--) { number = number.setScale(i, RoundingMode.HALF_UP); }
which is a rather weird way of rounding, and gives some unintuitive (at least to me) results.