How does java.math.RoundingMode work?

I have problems with rounding. In particular, after reading through all javadoc, I was expecting the following code:

int n = (integer between 0 and 9, included) new BigDecimal(n + 0.555d).setScale(2, RoundingMode.HALF_UP).doubleValue() 

to return n + 0.56 . Instead, these are the return values ​​for n from 0 to 4 :

  new BigDecimal(0.555d).setScale(2, RoundingMode.HALF_UP).doubleValue() 0.56 new BigDecimal(1.555d).setScale(2, RoundingMode.HALF_UP).doubleValue() 1.55 new BigDecimal(2.555d).setScale(2, RoundingMode.HALF_UP).doubleValue() 2.56 new BigDecimal(3.555d).setScale(2, RoundingMode.HALF_UP).doubleValue() 3.56 new BigDecimal(4.555d).setScale(2, RoundingMode.HALF_UP).doubleValue() 4.55 

I also tried changing the rounding mode:

 int n = (integer between 0 and 9, included) new BigDecimal(n + 0.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue() 

expecting n + 0.55 as a result for each n . Instead, the return values ​​are exactly the same as in the previous example:

  new BigDecimal(0.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue() 0.56 new BigDecimal(1.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue() 1.55 new BigDecimal(2.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue() 2.56 new BigDecimal(3.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue() 3.56 new BigDecimal(4.555d).setScale(2, RoundingMode.HALF_DOWN).doubleValue() 4.55 

Did I miss something?

+4
source share
3 answers

The problem is that double is not an exact representation, and you are rounded based on this inaccurate number.

 BigDecimal bd = new BigDecimal(1.555d); System.out.println("bd=" + bd); bd = bd.setScale(2, RoundingMode.HALF_UP); System.out.println("after rounding bd=" + bd); double d = bd.doubleValue(); System.out.println("after rounding d=" + d); 

prints

 bd=1.5549999999999999378275106209912337362766265869140625 after rounding bd=1.55 after rounding d=1.55 

but

 BigDecimal bd = BigDecimal.valueOf(1.555d); System.out.println("bd=" + bd); bd = bd.setScale(2, RoundingMode.HALF_UP); System.out.println("after rounding bd=" + bd); double d = bd.doubleValue(); System.out.println("after rounding d=" + d); 

prints

 bd=1.555 after rounding bd=1.56 after rounding d=1.56 

This works because BigDecimal.valueOf does some extra rounding depending on how the double will be displayed if you printed it.


However, I would not use BigDecimal if performance / simplicity is not a problem.

 double d = 1.555d; System.out.println("d=" + d); d = roundToTwoPlaces(d); System.out.println("after rounding d=" + d); public static double roundToTwoPlaces(double d) { return ((long) (d < 0 ? d * 100 - 0.5 : d * 100 + 0.5)) / 100.0; } 

prints

 d=1.555 after rounding d=1.56 

Details Double your money again compares the performance of different rounding methods.

+7
source

0.555d is the double value. It can be a little more than .555 or a little less.

+1
source

Rounding mode is used to round the decimal value.

You can use with.

 double DecimalValue = 3.1452; BigDecimal decimal = new BigDecimal(DecimalValue).setScale(2, RoundingMode.DOWN); 

=>

  RoundingMode.CEILING 

The rounding of the mode is rounded to positive infinity. For positive values, this rounding mode behaves like UP, for negative values ​​like DOWN. Rule: x.round() >= x

 RoundingMode.DOWN 

Rounding mode where values ​​are rounded to zero. Rule: x.round().abs() <= x.abs()

 RoundingMode.DOWN 

Rounding of the mode is rounded to negative infinity. For positive values, this rounding mode behaves like DOWN, for negative values ​​like UP. Rule: x.round() <= x

 RoundingMode.HALF_DOWN 

Rounding mode, where values ​​are rounded to the nearest neighbor. Links are broken by rounding down.

 RoundingMode.HALF_EVEN 

Rounding mode, where values ​​are rounded to the nearest neighbor. Ties are broken by rounding to an even neighbor.

 RoundingMode.HALF_UP 

Rounding mode, where values ​​are rounded to the nearest neighbor. Links are broken by rounding.

  RoundingMode.UNNECESSARY 

A rounding mode in which rounding operations raise an ArithmeticException for the case when rounding is necessary, i.e. for the case when the value cannot be accurately represented.

 RoundingMode.UP 

Rounding mode, where positive values ​​are rounded to positive infinity and negative values ​​to negative infinity. Rule: x.round().abs() >= x.abs()

0
source

All Articles