Search code examples
javaroundingprecisiondivisionbigdecimal

Issue with rounding aftrer division of BigDecimal values. Java


I've got a problem with the result of division of BigDecimal instances. My program:

public class DecimalPrecision

public static void main(String[] args) {

    MathContext mathContext = new MathContext(25, RoundingMode.HALF_UP);
    System.out.println(new BigDecimal("0.1111111111111111111111111").divide(new BigDecimal("3"), mathContext).toString());

    }

The result is the following: 0.03703703703703703703703703 But the correct result is: 0.03703703703703703703703704

Basically my program rounded the last digit, which is 7, to 3, not to 4. Why is it so? In mathContext I specified rounding mode HALF_UP. Probably I've got a gap in knowlegde on the issue but I was sure that HALF_UP rounds to a bigger value.

This problem can be sorted out in the next way:

    value1 = value1.divide(value2, 10000, RoundingMode.HALF_UP);
    return new BigDecimal(value1.toString()).round(mathContext);

But in my taste there's something wrong with parsing the result to a String and then create new properly rounded BigDecimal. I'm asking for your help, how can I resolve this problem without resorting to any strings? Thanks in advance.


Solution

  • You are starting with a 25 digit number and performing an operation with a precision of 25 digits so you can expect that the last digit might be wrong. The solution is to use more digits than you need and round the result.

    BigDecimal oneNinth25 = BigDecimal.ONE.divide(BigDecimal.valueOf(9), 25, BigDecimal.ROUND_HALF_UP);
    BigDecimal oneNinth26 = BigDecimal.ONE.divide(BigDecimal.valueOf(9), 26, BigDecimal.ROUND_HALF_UP);
    MathContext mathContext = new MathContext(25, RoundingMode.HALF_UP);
    
    System.out.println("1/9 to 25 digits / 3 = " + 
                       oneNinth25.divide(BigDecimal.valueOf(3), mathContext));
    System.out.println("1/9 to 26 digits / 3 = " + 
                       oneNinth26.divide(BigDecimal.valueOf(3), mathContext));
    

    prints

    1/9 to 25 digits / 3 = 0.03703703703703703703703703
    1/9 to 26 digits / 3 = 0.03703703703703703703703704