0

I have created the following helper function for rounding decimals:

public static double round(double value, int places, RoundingMode roundingMode) {
    if (places < 0) throw new IllegalArgumentException();

    BigDecimal bd = new BigDecimal(value);
    bd = bd.setScale(places, roundingMode);
    return bd.doubleValue();
}

I am confused by the results I get when using RoundingMode.CEILING:

round(2.0, 0, RoundingMode.CEILING); // returns 2, which is expected
round(2.180, 2, RoundingMode.CEILING); // returns 2.19, which seems odd as I expected 2.18

Could somebody please explain why in the second call, the value is effectively rounded up to 2.19?

trajan
  • 416
  • 1
  • 4
  • 10
  • 1
    Have you check how you `bd` looks like when you use `2.180`? You should/might get a value like `2.180000000000000159872115546022541821002960205078125`. – Tom Sep 30 '17 at 11:05
  • 1
    The problem here is that the decimal number 2.180 (in contrast to 2.0) does not have an exact representation as a double value. It happens, the nearest double value is slightly larger. – Henry Sep 30 '17 at 11:16
  • @Tom you are right, indeed the 2.180 value is being approximated before being scaled/rounded. Any ideas how to best fix the round() method to correct for this issue when using `RoundingMode.CEILING` and `RoundingMode.FLOOR`? – trajan Sep 30 '17 at 11:25
  • 2
    what happens when you use the String constructor, `new BigDecimal("2.180")`? – President James K. Polk Sep 30 '17 at 11:26
  • 1
    @JamesKPolk That would work, because it already applies a scale and would therefore "ignore" the inaccuracy. OP could also use `new BigDecimal(String.valueOf(value))`. – Tom Sep 30 '17 at 11:27
  • @JamesKPolk - that works. Thank you! – trajan Sep 30 '17 at 11:45

0 Answers0