Float X Double (Possible loss of Precision)

13 respostas
lincolngadea

Olá amigos,

Estou iniciando no Java, gostaria de uma ajuda com relação ao Float e Double.

Porque não consigo usar o float no Código abaixo? Só funciona com o Double, mas teoricamente o tipo numérico deveria funcionar no Float também.

import javax.swing.JOptionPane;
class valor_carro
{
      public static void main(String args[])
      {
         float CCONS, CFAB, PERC_VEND, IMP;

         CFAB = Float.parseFloat(JOptionPane.showInputDialog("Digite o Valor do Custo do Automóvel: "));
         PERC_VEND = CFAB - (CFAB * 0.75); //Percentual do vendedor é 25% do custo de Fábrica
         IMP = CFAB - (CFAB * 0.55); //O Imposto é 45% do custo de Fábrica

         CCONS = CFAB + PERC_VEND + IMP;

         JOptionPane.showMessageDialog(null,"O Custo do Consumidor é R$"+CCONS);

      }
}

13 Respostas

michetti

O Valor a ser calculado é muito grande, por isso usar o double.

lincolngadea

Obrigado pela resposta.

ttelsen

lincolngadea - se vais trabalhar com valores monetário te recomendo a usar BigDecimal, pois, mesmo o double perde precisão.

Ataxexe

Na verdade, o ideal é ter um objeto para representar o dinheiro. Um exemplo bem simples seria dividir 1 real entre 3 pessoas. Quanto isso daria?

Uma resposta certa seria: 33 centavos, 33 centavos e 34 centavos. Isso porque no dinheiro existe uma unidade indivisível e é preciso representá-la corretamente (apesar de podermos dividir 1 real entre 3 pessoas, é impossível representar 1/3 de real).

Eu, particularmente, prefiro utilizar um tipo inteiro para a quantidade em unidades indivisíveis e outro tipo inteiro para identificar a quantidade de dígitos fracionários (lembrando que existem moedas que não possuem casas decimais, como o Yen.

lincolngadea

Então, eu dei uma implementada e usei o DecimalFormat, ainda não pesquisei na documentação para saber as diferenças, mas consegui um bom resultado com o DecimalFormat.

Quanto a usar números inteiros para representação da moeda, acredito que seja uma boa prática, vou lembrar disso nos meus estudos.

Se alguém poder me mandar o link da documentação atualizada eu agradeço.

Agradeço também a ajuda de vcs.

att

ViniGodoy

Especificamente sobre a mensagem do compilador (a solução correta, em termos de dinheiro, é o que o ataxexe indicou).

O compilador dá o erro de “Possible loss of precision” por causa dos valores ordinais, ou seja, os diretamente escritos no código. Todo número sem casa decimal escrito diretamente no código é int. E todo número com casa decimal é double. Portanto:

PERC_VEND = CFAB - (CFAB * 0.75);

O 0.75 nesse código força o resultado para double, e o compilador vai reclamar de perda de precisão ao tentar atribuir para PERC_VEND que é float.

Para evitar esse erro, simplesmente use a letra f, que indica para o compilador que seu ordinal é um float:

PERC_VEND = CFAB - (CFAB * 0.75f);

Isso resolve o warning, mas não o problema da lógica de negócios. Mas resolvi explicar pois em outras situações, como em computação gráfica, é útil trabalhar com floats, mesmo com imprecisão.

lincolngadea

Muito bom, Nesse caso seria uma boa prática usar o double em situações que preciso informar o valor direto no código?

ViniGodoy

Como sempre, depende. No caso de aplicações de computação gráfica, onde você tem milhares de valores float, o resultado ocuparia mais memória do que o desejável.

O que geralmente define se você precisa de float, double ou outra estrutura mais complexa é a precisão desejada do resultado.

De maneira geral, o double é desejável sobre o float.

Mas tipos de ponto flutuante dificilmente podem ser usados em computações financeiras, ou mesmo em boa parte da matemática do dia-a-dia, pois sua precisão varia de valor para valor (e de arquitetura para arquitetura), e o que torna o resultado um tanto imprevisível.

Nesses casos, é melhor usar matemática de ponto fixo (como o tipo currency, do c#) ou então, alguma classe que use uma representação decimal (como é o caso do BigDecimal, que representa na forma de fração, usando 2 variáveis para o denominador e numerador).

lincolngadea

Mas, eu não poderia usar o DecimalFormat? não surtiria o mesmo efeito?

ViniGodoy

O decimal format apenas formata o resultado. Ele não interfere nos cálculos.

Usando o exemplo do ataxexe. Você tem 1 real. Dividiu entre 3 pessoas. E então, uma dessas multiplicou por 1000 esse rendimento.

Quanto essa pessoa terá ao final? Se usar o DecimalFormat, ela terá 333,33 reais. Usando uma classe para tipos monetários, ela terá R$330,00. Isso porque, após a divisão ela só poderia ter R$0,33 e não R$0,[telefone removido]…

Cuidado, pois calculos financeiros tendem a se acumular. Juros, por exemplo, incidem mês-a-mês, em cascata. E esses centavinhos acabam resultando numa enorme diferença.

Talvez não tenha muita relevância num trabalho escolar (e só formatar o resultado realmente atenderia), mas certamente, fará toda diferença numa aplicação real.

lincolngadea

Caramba, entendi tudo, muito obrigado pela explicação, vou pesquisar mais sobre o bigDecimal.

lincolngadea

ViniGodoy, mas nesse caso como eu implementaria o BigDecimal? estou um pouco perdido em como posso usar isso com variáveis…

ViniGodoy
Criado 26 de janeiro de 2014
Ultima resposta 27 de jan. de 2014
Respostas 13
Participantes 5