Problemas com arredondamento do Big Decimal

4 respostas
V

Eu possuo o seguinte código

Random gerador = new Random();
double dado = gerador.nextInt(6) + 1;
dado = dado/1000 %.3f;

double dado2 = gerador.nextInt(6) + 1;
dado2 = dado2/1000 %.3f;

double valorTotalJ1 = Jogo.jogadores.get(i).getTotalPontos();
double valorTotalJ2 = Jogo.jogadores.get(j).getTotalPontos();
BigDecimal dadojogador1 = new BigDecimal(dado);
BigDecimal dadojogador2 = new BigDecimal(dado2);

totalJogador1 = dadojogador1.add(totalJogador1).setScale(3, RoundingMode.DOWN);
totalJogador2 = dadojogador2.add(totalJogador2).setScale(3, RoundingMode.DOWN);

O problema é que esse valor não pode ser de jeito nenhum arredondado por uma regra de negócio, por exemplo, se o resultado do dado1 for 0.006 e o total do jogador 31.15 a soma tem que ser exatamente 31.156 e eu não consigo fazer isso de jeito nenhum, se eu desligar o rounding o java retorna o erro aritmético, alguém tem alguma ideia de como fazer isso?

4 Respostas

peczenyj

O seu problema é de definição.

qual é a precisão que vc precisa? quantas casas depois da virgula?

se vc pode definir, então provavelmente vc precisa de aritmetica de ponto fixo.

vou dar um exemplo: vc não vai usar BigDecimal ou Float ou seja la o que for para dinheiro. não existe meio centavo ( tem aquelas bizarrices de posto de gasolina mas esqueça isso ).

se não existe meio centavo, então vc deveria trabalhar com… centavos! sim esta é uma possibilidade.

se vc tem 0.006 e 31.15, isso não é diferente de ter 6 + 31150

mas vc sabe que tem um ponto decimal ai.

crie uma classe Pontuação que contem ‘micro pontos’ e saiba fazer as abstrações necessarias.

e se vc tentar converter isso pra double ou BigDecimal vc vai ter os mesmos problemas. nao converta pra tipo numerico que vai te introduzir imprecisão.

rmendes08

O problema é que você está usando o construtor BigDecimal(double). Este construtor é do mal, e quem fez merece boneco de vodoo reverso. Para construir um BigDecimal a partir de um double você tem que usar o método BigDecimlal.valueOf(double).

rmendes08

Trabalhar somente com inteiros não resolve o problema. Por exemplo, parcelar uma dívida 10000 centavos em 3x vai gerar uma dízima do mesmo jeito, e fatalmente você vai precisar truncar o valor.

A

Na verdade trabalhar com inteiros ajuda justamente a resolver esse problema.

O que geralmente acontece quando você parcela uma dívida de 100 em 3x, é ter 3 parcelas: 33.33, 33.33 e 33.34.

Trabalhar com inteiro te força a pensar nesse resto quando se faz divisoes e daí você aplica uma estratégia pra isso (como jogar o resto na última parcela).

Claro que ao invés de espalhar essa lógica pelo sistema, geralmente se encapsula tudo numa classe só que lida com esses cálculos.

Criado 29 de setembro de 2016
Ultima resposta 29 de set. de 2016
Respostas 4
Participantes 4