Conversao de float pra string com erro

11 respostas
G

tenho um numero 10.80F.
multiplico ele por 100 e converto pra int usando o wrapper. mas ele me mostra 1079. Por quê?

11 Respostas

T

Como é que você fez? Não consegui repetir o seu problema.

G

eh um metodo estatico de uma classe auxiliar … o codigo do metodo eh …

public static int formatToIntValue( float fValue){ Float f = new Float( fValue * 100); return f.intValue(); }
isso vai direto na pagina com scriptlets.

T

Ainda não consegui reproduzir seu problema. :stuck_out_tongue:

class Teste1079 {

    // seu código
    public static int formatToIntValue( float fValue){
         Float f = new Float( fValue * 100);
         return f.intValue();
    }
	// como eu escreveria - note que isso evita criar um wrapper à toa
	public static int formatToIntValue2 (float fValue) {
	    return (int) Math.round (fValue * 100);
	}
	
    public static void main(String[] args) {
	     System.out.println (formatToIntValue (10.80f)); // imprime 1080
	     System.out.println (formatToIntValue2 (10.80f)); // imprime 1080
    }
}
G

eu tentei reproduzir … com um main … mas tbm naum deu certo … mas na pagina eh isso q acontece …

esse eh o source …

<!-- <%=oCart.getTotal()%> --> <input type="hidden" name="Spv" value="<%= BjShoppingCart.formatToIntValue( oCart.getTotal())%>">

esse eh o out …

<!-- 9.9 --> <input type="hidden" name="Spv" value="989">

G

Substituí …

Float f = new Float( fValue * 100); return f.intValue();
por …

(int) Math.round (fValue * 100)

e funcionou !
Pode me explicar a diferença ?

T
  1. Se possível, nunca use float para fazer contas. Use sempre double. Por incrível que pareça, double chega até a ser um pouco mais rápido.

  2. oCart.getTotal() não deve estar voltando o valor 10.79f, e sim um resultado de uma soma, que deve ser algo como 10.78998 ou coisa parecida.
    Mais um motivo para usar double em vez de float - a precisão de um float é de cerca de 6 algarismos significativos, que é muito pouco para lidar com dinheiro.
    Use double, que tem cerca de 15 algarismos significativos de precisão.

jcatino

grustk:
Substituí …

Float f = new Float( fValue * 100); return f.intValue();
por …

(int) Math.round (fValue * 100)

e funcionou !
Pode me explicar a diferença ?

Você arredondou o resultado da multiplicação de um float, que está trazendo uma precisão muito maior à desejada, e quando convertida para Integer o resultado final distorce o que vc esta esperando como resposta.

Pense que um float é um ponto flutuante. Portanto , é armazenado em duas partes, sendo uma a mantissa e outra o expoente, para compor um número em notação científica.

Com isso um float / double podem armazenar valores com decimais muito precisos como 54,18828734.

Mas o lado ruim é que vc está querendo ter como resposta 10,98 e ele gravou algo como 10,9777777777799998, para conversar a precisão desejada.

A verdade é que se vc está querendo representar valores de moedas (na programação também chamados de ‘amount’ ou ‘montantes’), o melhor é gravar num Integer mesmo e dividir por 100 para não ter esses problemas de arredondamento. Outra solução trabalhosa mas elegante é trabalhar com BigDecimal, sempre indicando a precisão (scale) nas operações desejadas como adição, substração, etc…

Resumo da estória: float e double não servem para manipular valores de moedas, e diria até que é perigoso fazê-lo, combinando ainda resultados em inteiros, pois os arredondamentos necessários vão gerar distorções. Float e Double servem para armazenar valores com várias casas decimais, ou para valores muito altos (acima de bilhões) com precisão de decimais.

jcatino

thingol:
1) Se possível, nunca use float para fazer contas. Use sempre double. Por incrível que pareça, double chega até a ser um pouco mais rápido.

  1. oCart.getTotal() não deve estar voltando o valor 10.79f, e sim um resultado de uma soma, que deve ser algo como 10.78998 ou coisa parecida.
    Mais um motivo para usar double em vez de float - a precisão de um float é de cerca de 6 algarismos significativos, que é muito pouco para lidar com dinheiro.
    Use double, que tem cerca de 15 algarismos significativos de precisão.

Embora com double o problema apareça menos, ele também existe, e se acumular / arredondar valores, sempre vão aparecer distorções. Mas concordo que no caso específico, double também vai funcionar.

T

Usar “double” para lidar com moeda é possível mas você tem de tomar muito cuidado.

(Ou seja, seu programa funciona bem com você, que sabe fazer contas, mas aí vai ser mantido por alguém que não conhece aritmética de ponto flutuante e não entende porque 3.0 * (1.0 / 3.0) != 1.0, e acaba dando pau !

Normalmente você é obrigado a usar double só quando você tem de calcular juros compostos ou alguma outra coisa que não permite usar o feijão-com-arroz de calcular as coisas em centavos e usar um “long”.
Em VB 6.0 existe um tipo “Currency” que é na verdade um “long” (64 bits) que calcula as coisas em centésimos de centavos, e é convertido automaticamente de e para Double. Seria interessante se existisse algum assim em Java.

renatoes

a indicação para uso monetario eh a classe BigDecimal n eh?

T

BigDecimal é um pouco chato de usar.
Eu só aconselharia seu uso se:

  • Você só precisa fazer somas, subtrações, multiplicações e divisões;
  • Sabe que você tem de arredondar o resultado da divisão ou da multiplicação para ter as 2 casas depois da vírgula (no caso de valores monetários, em centavos), ou passar os parâmetros adequados para que as rotinas já façam esse arredondamento;
  • Tiver paciência para converter as suas fórmulas
  • Ficar convertendo e desconvertendo de/para double se tiver alguma fórmula mais complicada (exemplo: cálculo de juros compostos).
Criado 26 de dezembro de 2006
Ultima resposta 27 de dez. de 2006
Respostas 11
Participantes 4