Accuracy error in account with BigDecimal

3

I have the class below which has a different value than when I use the calculator. I searched on BigDecimal , but I must be missing something when submitting the result.

What I have to do is:

  

4.5% of 8410 = 378.45

But using the class below is only 378. The decimal places I do not know how to display.

public class Teste {
    public static void main(String[] args) {
        BigDecimal valorInicial = new BigDecimal("8410");
        BigDecimal contanteDivisor = new BigDecimal("100");
        BigDecimal resultDivisao = valorInicial.divide(contanteDivisor, new MathContext(2, RoundingMode.HALF_EVEN));
        BigDecimal resultado = resultDivisao.multiply(new BigDecimal("4.50"));

        System.out.println("Resultado: " + resultado);           
    }    
}
    
asked by anonymous 09.12.2016 / 17:00

1 answer

6

Remove MathContext :

public class Teste {
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        BigDecimal valorInicial = new BigDecimal("8410");
        BigDecimal contanteDivisor = new BigDecimal("100");
        BigDecimal resultDivisao = valorInicial.divide(contanteDivisor);
        BigDecimal resultado = resultDivisao.multiply(new BigDecimal("4.50"));

        System.out.println("Resultado: " + resultado);           
    }    
}

When you add new MathContext(2, RoundingMode.HALF_EVEN) to the BigDecimal call, you are telling him to round the division value to the nearest number, considering up to two digits of precision.

With this, by dividing 8410 by 100 according to the excerpt from your code below:

BigDecimal valorInicial = new BigDecimal("8410");
BigDecimal contanteDivisor = new BigDecimal("100");
BigDecimal resultDivisao = valorInicial.divide(contanteDivisor, new MathContext(2, RoundingMode.HALF_EVEN));

resultDivisao should be 84.10 , but with the rounding using a precision of only two digits the result is 84 .

See the ideone difference between quotients, with and without rounding.

On the next line,

BigDecimal resultado = resultDivisao.multiply(new BigDecimal("4.50"));

You are actually multiplying 84 by 4.5 , which results in 378 that your code is displaying, in> 84.10 * 4.50 = 378.45 );

It is important to note that if the code intention was to limit the number of decimal places in the division result, you must use the setScale method, since we are talking about the scale (digits after the comma) and not precision ( significant digits).

For this, you can adapt the division line as below:

BigDecimal resultDivisao = valorInicial.divide(contanteDivisor)
        .setScale(2, RoundingMode.HALF_EVEN);

When the division result can be a non-exact number, it is also necessary to work with precision to avoid a ArithmeticException . Scaling can be done after splitting:

BigDecimal valorInicial = new BigDecimal("8411");
BigDecimal contanteDivisor = new BigDecimal("101");
BigDecimal resultDivisao = valorInicial
        .divide(contanteDivisor, new MathContext(10, RoundingMode.HALF_EVEN))
        .setScale(2, RoundingMode.HALF_EVEN);

In this case the result of dividing 8411 by 101 with 10-digit precision is 83.27722772 . After scaling, the final result is 83.28 .

That is, precision sets the number of digits to be computed while the scale adjusts the number of decimal places.

See the corrected code running on IDEONE .

References:

Documentation: RoundingMode

Documentation: BigDecimal .setScale

BigDecimal setScale and round

    
09.12.2016 / 17:16