Java calculando errado

7 respostas
R_chieck

Olá, abri este tópico porque estou com um baita problema no calculo de valores com java.
Foi por acaso que me deparei com isto.
Por exemplo:

System.out.println(37.455 + 0.01);

Isto deveria retornar 37.465
Porem, retorna 37.464999999999996
Este é um exemplo entre muitos outros.
Já pensei que fosse a arquitetura como o processador ou SO, mas não é.
Alguem aí já passou por isso ou sabe oque pode ser?

7 Respostas

C

Iae cara.

Na verdade pontos flutuantes são “arredondados” pelo fato da base binária não oferecer precisão. Se você pesquisar na internet vera que isso é um caso muito comum.

Para dar uma burlada nesse caso, utilize a classe BigDecimal, inicializando os valores como String.

public static void main(String[] args) {
		System.out.println(37.455 + 0.01);
		BigDecimal b = new BigDecimal("37.455");
		BigDecimal b1 = new BigDecimal("0.01");
		System.out.println(b.add(b1));
	}

Talvez alguém tem uma solução melhor, mas é esta que me ocorre agora.

Abraço.

R_chieck

Ola,
vlw a resposta, funcionou.
Mas no meu caso eu faria uma série destes cálculos com laços com dados vindos do banco.
Este método não prejudicaria muito o desempenho por ter de ficar sempre fazendo um parser para String e vice-versa?

XOOM

R$chieck:
Ola,
vlw a resposta, funcionou.
Mas no meu caso eu faria uma série destes cálculos com laços com dados vindos do banco.
Este método não prejudicaria muito o desempenho por ter de ficar sempre fazendo um parser para String e vice-versa?

Tenta assim que dá certo:

System.out.println(37.455f + 0.01f);
Y

crisaltmann:
Iae cara.

Na verdade pontos flutuantes são “arredondados” pelo fato da base binária não oferecer precisão. Se você pesquisar na internet vera que isso é um caso muito comum.

Para dar uma burlada nesse caso, utilize a classe BigDecimal, inicializando os valores como String.

public static void main(String[] args) {
		System.out.println(37.455 + 0.01);
		BigDecimal b = new BigDecimal("37.455");
		BigDecimal b1 = new BigDecimal("0.01");
		System.out.println(b.add(b1));
	}

Talvez alguém tem uma solução melhor, mas é esta que me ocorre agora.

Abraço.

Realmente R$cheick assim vai funcionar perfeitamente , e não vai deixar seu sistema pesado pois ele só vai somar duas variaveis e exibir o resultado.É uma ação muito rapida do sistema, sem alteração alguma no desempenho, pelo menos acho que é hehe abraços

R

BigDecimal é a solução preferencial, certamente. O desempenho da sua aplicação vai diminuir um pouco, mas esse é o preço a pagar pela exatidão. Às vezes a exatidão não é um requisito rígido - em várias aplicações científicas, um pouco de arredondamento é perfeitamente aceitável. Mas, em aplicações financeiras, não se pode abrir mão da exatidão. No fim das contas, a menos que você esteja fazendo cálculos muito pesados, o uso de BigDecimal não vai prejudicar o desempenho, então não creio que você precise perder o sono por causa disso.

R_chieck

ok,
a principio vai ter de ser exato, pois é para um sistema ERP.
vlw gnt, obrigado, abraço

sergiotaborda

O uso de double ou float para representar dinheiro é fria. Usar BigDecimal é melhor, mas complicado.
A melhor solução é usar o padrão Money. Se vc só usa uma moeda vc pode implementar Money trivialmente usando long. E ai não ha perda nenhuma de precisão.
Para soluções mais sofisticadas poderia usar o prorpio BigDecimal ou o padrão Ratio.

Criado 30 de agosto de 2012
Ultima resposta 3 de set. de 2012
Respostas 7
Participantes 6