2

I'm facing an issue while trying to round up the decimal places in a number to the nearest hundered-thousandth digit.

Example :

BigDecimal num1 = BigDecimal.valueOf(0.38871551);
MathContext mc = new MathContext(5);
System.out.println(num1.round(mc));

The output is 0.38872 which is as expected. All good so far. Let's take another example :

BigDecimal num1 = BigDecimal.valueOf(1.1680418);
MathContext mc = new MathContext(5);
System.out.println(num1.round(mc));

The output is 1.1680. This is where the problem arrises. What I want is the output to be 1.16804 but the rounding seems to eat up the 4 instead of leaving it as it is.

I tried different rounding modes but this is what I get :

  • RoundMode.UP gives 1.1681
  • RoundingMode.HALF_UP or RoundingMode.HALF_DOWN give 1.1680 and so on..

How do I get the desired output :

  • 0.38871551 should round to 0.38872
  • 1.1680418 should round to 1.16804
  • 0.55052984 should round to 0.55053

I even tried rounding to the 6th decimal place instead of the 5th but I'm not able to find the right combination that gives me the desired output as shown above.

K.Oleksiak
  • 325
  • 1
  • 2
  • 15
Ping
  • 587
  • 5
  • 27
  • See [this](https://stackoverflow.com/questions/153724/how-to-round-a-number-to-n-decimal-places-in-java?rq=1) question. – itsmysterybox Oct 25 '18 at 08:29

3 Answers3

3

You can try it with setScale Function of BigDecimal

num1 = num1.setScale(5, BigDecimal.ROUND_HALF_UP);
Jannik
  • 965
  • 2
  • 12
  • 21
  • This works as well. But why `HALF_UP` and not `HALF_EVEN` like the other answer? – Ping Oct 25 '18 at 08:29
  • `HALF_UP` rounds up the digit to the next higher number but `HALF_EVEN` although similar to `HALF_UP` rounds to the nearest even number when equidistant to both numbers. See docs https://docs.oracle.com/javase/7/docs/api/java/math/RoundingMode.html – Jannik Oct 25 '18 at 08:36
  • Changed mine to HALF_UP as well... but it's all a matter of what you need. Anyway, `setscale(int, RoundingMode)` should be preferred over `setscale(int, int)`. – dly Oct 25 '18 at 08:45
2

MathContext(int) rounds the number to that amount of digits, taking the whole number into account instead of just the digits after the comma.

say you use these numbers:

    BigDecimal ten = BigDecimal.valueOf(10.55052984);

    MathContext five = new MathContext(5);
    MathContext two = new MathContext(2);

    System.out.println(ten.round(five));
    System.out.println(ten.round(two));

It will produce a number rounded to the 5th or 2nd digit, regardless of its position:

10.551
11

This should work:

    BigDecimal num1 = BigDecimal.valueOf(0.38871551);
    System.out.println(num1.setScale(5, RoundingMode.HALF_UP));

    num1 = BigDecimal.valueOf(1.1680418);
    System.out.println(num1.setScale(5, RoundingMode.HALF_UP));

    num1 = BigDecimal.valueOf(0.55052984);
    System.out.println(num1.setScale(5, RoundingMode.HALF_UP));

0.38872
1.16804
0.55053

dly
  • 1,080
  • 1
  • 17
  • 23
  • Thanks. This looks promising. Will this always work correctly as per the rounding rules of mathematics for any number? Also, I tired this approach by using a `Mathcontext` and `round` method. Why does this give the desired output when you use `setScale` but doesn't give the desired output when you use `round` with a `MathContext`?. Also, why `HALF_EVEN` and not `HALF_UP`? – Ping Oct 25 '18 at 08:25
  • `MathContext(5)`simply means the whole number is 5 digits long. So a number between 10 and 99 would only have three more digits. – dly Oct 25 '18 at 08:30
  • @Ping I've added an explanation to the answer now. – dly Oct 25 '18 at 08:38
1

you can try this way

DecimalFormat df = new DecimalFormat("#.00000");

System.out.print(df.format(1.1680418)); //1.16804
Orgil
  • 251
  • 4
  • 19