Problema com arredondamento Float

Estou construindo um sistema na faculdade (trabalho) e estou com a seguinte situação:

tenho o item do pedido e o pedido

ItemPedido:
private Float preco;
private Integer quantidade;

Pedido:
private Float total;

eu estou gravando o total no pedido só pra fica mais rápido a consulta futuramente, neste meu caso é necessário!

em fim… eu fi um pedido assim:
tenho dois itempedido:
1 - quantidade: 23 e preço: 1239,84
2 - quantidade: 23 e preço: 300

total item pedido1: 28516,32
total item pedido2: 6900

total que aparece no pedido: 35416,3

total que deveria aparecer: 35416,32

ou seja, quando tem a virgula ele come uma casa, a ultima…
testei várias situações e sempre deu a mesma coisa, ele só aparece uma casa a direita deopis da virgula…

alguem sabe como resolver?

para isso você deve tratar seu numero com a classe NumberFormat, para definir o numero de casas decimais, ou se quiser, dar um jeitinho brasileiro parseando teu numero pra string, usar um array com substring e reinventar a roda… fica a seu critério.

Não use Float ou float para fazer contas com dinheiro. A precisão do float é de exatamente 6 dígitos, e é por isso que ele “comeu uma casa”, porque você quis que ele usasse 7 dígitos ( 28516,32 ).

Use double ou então BigDecimal, dependendo da sua necessidade (double se aceitar no máximo 15 dígitos, e BigDecimal se aceitar que seja mais lento e mais chato de trabalhar que o double - a precisão é ilimitada no caso do BigDecimal).

De certo modo, o “float” é como se fosse uma câmera fotográfica daqueles celulares bem vagabundos (resolução VGA, 640 x 480, o que dá 0,3 megapixels) e o “double” é como se fosse uma câmera fotográfica de um celular mais recente (5 megapixels).

Ambos tiram fotos, mas você tem resoluções bem diferentes.

Para você tirar uma foto e imprimi-la em um jornal, não vai usar uma câmera fotográfica de 0,3 megapixel. Talvez use uma câmera de 17 megapixels profissional :slight_smile:

O “BigDecimal” seria como uma foto em filme - você não distingue os pixels, mas o filme é mais chato de usar e mais lento (você precisa revelar as fotos no laboratório, e cada rolo de filme pode tirar até 36 fotos apenas - além disso, para fazer tratamento de imagens dá bem mais trabalho, como alguém que já fez aqueles cursos de fotografia pode lhe dizer).
Mas você pode imprimir essa foto em um jornal.

Utilize o BigDecimal para estes casos, ele é um pouco mais trabalhoso mas as dores de cabeça com arredondamento praticamente somem.

Elas mudam de lugar - quando você precisa fazer uma divisão ou então algum cálculo que envolve funções trigonométricas ou algébricas - uma simples raiz quadrada já dá problemas; acho que foi postado aqui um exemplo de como se acha uma raiz quadrada com BigDecimal que era um bocadinho complicado.
Eu ainda prefiro usar o velho e bom double e usar o DecimalFormat nos lugares corretos.
Até porque certas coisas continuam inexatas, e você continua a ter de usar quebra-galhos: quando você precisa dividir um pagamento de R$ 1.000,00 em três parcelas, você não tem parcelas de 333,33333333333… e sim duas de 333,34 e uma de 333,32 (isso é feito para deixar o cliente mais contente porque a última prestação é menor :slight_smile: ).

A raiz quadrada com BigDecimal - é bem chatinha, por sinal.

Elas mudam de lugar - quando você precisa fazer uma divisão ou então algum cálculo que envolve funções trigonométricas ou algébricas - uma simples raiz quadrada já dá problemas; acho que foi postado aqui um exemplo de como se acha uma raiz quadrada com BigDecimal que era um bocadinho complicado.
Eu ainda prefiro usar o velho e bom double e usar o DecimalFormat nos lugares corretos.
Até porque certas coisas continuam inexatas, e você continua a ter de usar quebra-galhos: quando você precisa dividir um pagamento de R$ 1.000,00 em três parcelas, você não tem parcelas de 333,33333333333… e sim duas de 333,34 e uma de 333,32 (isso é feito para deixar o cliente mais contente porque a última prestação é menor :slight_smile: ).
[/quote]

Mas nestes casos, esses problemas ocorrem em números que não possuem representação decimal finita, como é o caso das dízimas. Nestes casos, a solução fica no algoritmo mesmo, como nesse exemplo do parcelamento. Para outros tipos de cálculo, sempre vale a pena simplificar as expressões, favorecer somas e subtrações ao invés de multiplicações e divisões por exemplo, para minimizar os erros.

O problema do double, é que mesmo para números com representação decimal finita, ainda assim você pode perceber precisão, tanto pelo limite de casas decimais quanto pelo fato de que como a representação é binária, alguns números simplesmente não podem ser expressos com precisão. Já no BigDecimal você não tem esse problema, pois a representação é arbitrária e dígito a dígito.

Bom, o Excel, que todo mundo usa para fazer contas com dinheiro, usa double mesmo, e nunca ninguém reclamou que ele faz as contas tão erradas assim :slight_smile:

[quote=entanglement]Bom, o Excel, que todo mundo usa para fazer contas com dinheiro, usa double mesmo, e nunca ninguém reclamou que ele faz as contas tão erradas assim :slight_smile:
[/quote]

E você tem o código fonte do Excel por acaso ?

Não é preciso ter o código-fonte do Excel para mostrar que ele faz as contas somente com double.

Basta fazer algumas contas com ele (diferenças de valores bem próximos) e mostrar os resultados com as formatações adequadas, e vai ver que comete exatamente os mesmos erros que o Java e o C quando trabalham com double.

Além disso, a velocidade de recálculo de uma planilha bem grande com o Excel é compatível com o tempo que se esperaria se ele usasse double, não alguma coisa como o Currency do C# ou o BigDecimal do Java.

Outra prova é olhar o fonte do módulo de planilhas do OpenOffice, que é compatível até ao nível de bugs com o Microsoft Office - ele também trabalha com double.

Fiz um teste no LibreOffice e realmente ele limita o número de casas decimais de um campo numérico. Ou seja, essas planilhas até podem ser boas para casos triviais, mas tem sua aplicação limitada. Não é a toa que existem software’s científicos como Mathematica e MatLab …

hehe muito legal essa discussão… usarei Double então, já irá sanar minha necessidade…

gostei da discussão, estou aprendendo muito ^^

Nem precisam de ir ao nível de casas decimais.

Coloquem 123456789012345678 numa célula do excel e ele vai transformar em 123456789012345000.

Mesmo o MatLab usa double em alguns casos :slight_smile: - e pior ainda, ele mostra os valores resultantes com 6 casas depois da vírgula apenas.
Por exemplo, quando ele vai fazer o cálculo de uma integral definida numericamente. Esse tipo de cálculo não é exato, portanto ele mostra só os algarismos significativos.

amigo com todo respeito, não discuta com o entanglement, pois vc ainda é um Master, enquanto e entanglement já é Hacker!

amigo com todo respeito, não discuta com o entanglement, pois vc ainda é um Master, enquanto e entanglement já é Hacker![/quote]

colega, não sei onde você quis chegar exatamente, mas baseando-me em fatos eu tenho o direito de argumentar e contra-argumentar com qualquer um.

amigo com todo respeito, não discuta com o entanglement, pois vc ainda é um Master, enquanto e entanglement já é Hacker![/quote]

colega, não sei onde você quis chegar exatamente, mas baseando-me em fatos eu tenho o direito de argumentar e contra-argumentar com qualquer um.[/quote]

É isso mesmo. Eu falo muita besteira, e se eu estiver escrevendo coisas erradas, por favor me corrijam - essa história de “Hacker” ou “Master” é só pela quantidade de posts, o que não é mérito para ninguém.
Tendo os argumentos corretos eu não só volto atrás como apóio completamente.
Eu posso ser um pouco “cavalo” (no sentido de grosseiro, afinal, sou do signo de Sagitário, que é um centauro - meio cavalo, meio homem :slight_smile: ) mas não sou “burro” (no sentido de “teimoso” - talvez seja “burro” no sentido de “pouco inteligente”).