Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rounding mode with BigDecimal in Java

The following code which uses RoundingMode.HALF_EVEN,

BigDecimal value1 = new BigDecimal("4.5");
value1=value1.setScale(0, RoundingMode.HALF_EVEN);

BigDecimal value2 = new BigDecimal("6.5");
value2=value2.setScale(0, RoundingMode.HALF_EVEN);

System.out.println(value1+"\n"+value2);

displays 4 and 6 respectively. It seems to me that it should display 5 and 7 respectively because the digit to the left of the discarded fractional part (which is 5 in this case) is odd. In this case, it performs RoundingMode.HALF_UP

And in case of RoundingMode.HALF_UP, RoundingMode.UP is performed when the discarded fractional part is >=0.5 (which is true), otherwise RoundingMode.DOWN is performed.

like image 818
Tiny Avatar asked Mar 12 '13 02:03

Tiny


1 Answers

The behavior is well described in the Javadoc:

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

So given the number 4.5, which falls right in the middle of the range of numbers between 4 and 5, when you call:

BigDecimal value1 = new BigDecimal("4.5").setScale(RoundingMode.ROUND_HALF_EVEN);

The runtime needs to figure out which neighbor to round too, aka, should it round to 4, or to 5? Normally it would round based on which value 4.5 is closer to, but in this case its close to both neighbors. Instead of arbitrarily picking the final result though, it picks the even number. This is the behavior of ROUND_HALF_EVEN. If you wanted to, you could specify ROUND_HALF_UP and the final result would have been 5, and not 4. Also, keep in mind that the determination about how to round is based on what the final result would be (and not on the decimal portion of the big decimal, as you seem to have assumed).

like image 126
Perception Avatar answered Sep 19 '22 02:09

Perception