Bigdecimal - Arredondamento?

Estou tentado arrendondar valores com BigDecimal para a matemática financeira.

BigDecimal bd = new BigDecimal(valor).setScale(2, RoundingMode.HALF_EVEN);
bd.doubleValue();

Valores 1,810 - Saida 1,81
Valores 1,811 - Saida 1,81
Valores 1,812 - Saida 1,81
Valores 1,813 - Saida 1,81
Valores 1,814 - Saida 1,81
Valores 1,815 - Saida 1,81 - Problema está aqui. Na matemática teria que arredondar para cima
Valores 1,816 - Saida 1,82
Valores 1,817 - Saida 1,82
Valores 1,818 - Saida 1,82
Valores 1,819 - Saida 1,82

Por mais que li sobre o assunto ainda não está claro para mim.

Se eu adiconar uma 4 casa decimal, percebi que o resulto está correto, exemplo abaixo para o codigo alterado.

BigDecimal bd = new BigDecimal(valor).add(new BigDecimal(0.0001));
bd = bd.setScale(2, RoundingMode.HALF_EVEN);
bd = new BigDecimal(valor).setScale(2, RoundingMode.HALF_EVEN);

Para o codigo acima os valores vão sair de forma correto.

Valores 1,810 - Saida 1,81
Valores 1,811 - Saida 1,81
Valores 1,812 - Saida 1,81
Valores 1,813 - Saida 1,81
Valores 1,814 - Saida 1,81
Valores 1,815 - Saida 1,82 - Problema Corrigido
Valores 1,816 - Saida 1,82
Valores 1,817 - Saida 1,82
Valores 1,818 - Saida 1,82
Valores 1,819 - Saída 1,82

  • Mais isso é uma boa pratica?
  • Corro risco de dar problema em outros cálculos?

O problema é o modo que você está instanciado o BigDecimal. O construtor BigDecimal(double) tenta converter o número a partir da representação de ponto flutuante, sendo assim, ele não consegue converter os dígitos exatos do número. Ao invés disso, você deve usar o método estático valueOf(). Veja:

BigDecimal bd1 = BigDecimal.valueOf(1.815).setScale(2, RoundingMode.HALF_EVEN); //resultado correto
BigDecimal bd2 = new BigDecimal(1.815).setScale(2, RoundingMode.HALF_EVEN); //resultado errado
2 curtidas

Na verdade boa parte da sua resposta está correta, o que faltou dizer que uma simples conversão faz o papel correto:

Ou seja, as duas formas são corretas, faltou um simples f para solucionar o problema das duas maneiras:

BigDecimal bd1 = BigDecimal.valueOf(1.815).setScale(2, RoundingMode.HALF_EVEN);

BigDecimal bd2 = new BigDecimal(1.815f).setScale(2, RoundingMode.HALF_EVEN);

as duas formas estão corretas agora.

1 curtida

Valeu galera!

Resolvido.

1 curtida