Precisão em Java de Double

Estou com o seguinte problema:

double a = 100.0;
double b = 100.0;
double c = 300.33;

double d = a+b+c;

sysout(d);

retorno = 533.329999999…

bem, visto que é apenas uma soma, sem divisão, não PODE acontecer…

Testei em 3 ambientes diferentes (SO e JRE)

gostaria de saber se alguém poderia me dizer como “passar por cima” disso, sem muita gambiarra…

Agradeço.

Tem certeza que você tá rodando exatamente esse código, sem nenhuma manipulação antes/depois?
Copiei e colei e rodei no Windows+Java5 e deu exatamente o resultado esperado (500.33)

300.33 não é um número exato em binário. Se quiser um número exato, em centavos:
a) Faça as contas todas em centavos (e use long)
b) Use BigDecimal
c) Faça as contas com double, mesmo, mas mostre arredondado com 2 casas depois da vírgula.

sim sim, esse código mesmo, tentei com BigDecimal anteriormente e também não deu certou

Linux 6_21
Windows 6_21
Windows 6_13

todos me retornaram o mesmo resultado
= /

[quote=entanglement]300.33 não é um número exato em binário. Se quiser um número exato, em centavos:
a) Faça as contas todas em centavos (e use long)
b) Use BigDecimal
c) Faça as contas com double, mesmo, mas mostre arredondado com 2 casas depois da vírgula.
[/quote]

A ideia do Long me custaria tempo demais, estamos em fase final de testes de um novo ERP
BigDecimal dá a mesma coisa = /
Tentei arredondar também, mas acaba que falta ou sobra decimais

Note que o arredondamento deve ser feito pela parte que mostra os números, não pela parte que faz contas. É só pensar no seguinte:

double d = 533.33;
System.out.println (d); // deve imprimir 533.329999999...
d = Double.parseDouble ("533.33");
System.out.println (d); // deve imprimir exatamente a mesma coisa. 

ou seja, é impossível representar 533.33 como um número “exato” em binário. O que você pode fazer é imprimir o número arredondado, com java.text.DecimalFormat.

[quote=entanglement]Note que o arredondamento deve ser feito pela parte que mostra os números, não pela parte que faz contas. É só pensar no seguinte:

double d = 533.33;
System.out.println (d); // deve imprimir 533.329999999...
d = Double.parseDouble ("533.33");
System.out.println (d); // deve imprimir exatamente a mesma coisa. 

ou seja, é impossível representar 533.33 como um número “exato” em binário. O que você pode fazer é imprimir o número arredondado, com java.text.DecimalFormat. [/quote]

uahauhauahauhauhauahuahauhauahuahauha

acreditem em mim ou não… testei com o BigDecimal e testei de novo com Double e, acreditem… deu 500.33…

WhatTheHell?

pois bem, AGORA SIM eu fiquei com dúvidas… estou a uma semana lendo sobre pontos flutuantes e de precisão dupla, testes atrás de testes…

e agora resolveu me mostrar o número certo…

Alguém explica???

e, sim, aquele código que mostrei era o que eu testava dia e noite…

O.o

Ola!

A resposta esta aqui:
http://blog.caelum.com.br/2010/07/15/arredondamento-no-java-do-double-ao-bigdecimal/

Use BigDecimal, usando o construtor que recebe String, nao double, ja que essa “falha” do double é planejada.

Paulo

Dê uma lida aqui:
http://www.guj.com.br/posts/list/68086.java#357907
http://www.guj.com.br/posts/list/84121.java#448928

Vou explicar uma coisa meio chata, mas que todo mundo deveria saber.

Em Java, C, C#, VB.NET, VB 6, C++, Fortran, Pascal/Delphi, etc., costuma haver dois tipos de dados de ponto-flutuante, chamados normalmente de “float” e “double”. (No VB são “single” e “double” e no Fortran, se não me engano, são “real” e “double precision”).
Como eles são implementados por hardware e seguem um determinado padrão (IEEE-754, normalmente uma mesma conta tem de dar resultados iguais em todas essas linguagens. TODAS. (OK, cada uma dessas linguagens usa um modo diferente de acertar alguns parâmetros no processador que na prática irão dar resultados ligeiramente diferentes - modos de arredondamento, comportamento quanto a divisão por zero e outras sutilezas previstas no padrão. Mas na prática deveriam dar o mesmo resultado).
Só que o Java imprime os números, por default, com o máximo possível de algarismos depois da vírgula - não só 6, como em C. Então isso é que provoca mostrar esses números esquisitos como “533.2999999997” ou coisas parecidas.
Na verdade, esse número foi a mesma coisa que um programa equivalente em C calcularia. Mas como em C só mostramos 6 casas depois da vírgula, por default, então você tem um número “533.300000” e você acha que ele fez as contas exatamente. Em outras linguagens (como Pascal/Delphi) há uma limitação parecida.
Se você não sabe lidar direito com esses números quebrados (ou arredondando, ou tomando outras providências), então use um tipo decimal (como o System.Decimal do C# ou o java.math.BigDecimal do Java). Para fazer contas de dinheiro, por exemplo, você tem de tomar bastante cuidado com double, já que você pode ter tal tipo de surpresas.

Galerê, valeu as respostas, isso eu tinha visto e talz, só não entendi por quê o mesmo código que mostrei no começo retornou o que eu queria dessa vez…

Ao que eu saiba, Java não tem lixo de memória de execuções anteriores, ou tem?
=x

Bom, iglander, a minha única explicação para o seu código é que, apesar de na IDE estar sendo mostrada uma versão, você estava executando outra versão de binário (por exemplo, quando a opção “Build Automatically” não está marcada no Eclipse).

Fora isso, não sei como explicar isso não… Do mau, hein! hehehe.

Mas pra resumir, então, você não tem problema nenhum, certo?

[quote=mtakeda]Bom, iglander, a minha única explicação para o seu código é que, apesar de na IDE estar sendo mostrada uma versão, você estava executando outra versão de binário (por exemplo, quando a opção “Build Automatically” não está marcada no Eclipse).

Fora isso, não sei como explicar isso não… Do mau, hein! hehehe.

Mas pra resumir, então, você não tem problema nenhum, certo?[/quote]

Não mais!

Só não me pergunte o porquê disso…

=x

agora eu flagrei o esquema do construtor em String do BigDecimal, fora isso, o resto eu já sabia. Valeuzão, galerê!

= D

amigo, copiei seu codigo, e colei no eclipse…

deu o resultado 500.33

nao deu esse numero como o seu.

abçssssssss