Pergunta

Eu tenho um flutuador primitivo e preciso como um duplo primitivo. Simplesmente lançar a bóia para dobrar me dá precisão extra de estranho. Por exemplo:

float temp = 14009.35F;
System.out.println(Float.toString(temp)); // Prints 14009.35
System.out.println(Double.toString((double)temp)); // Prints 14009.349609375

No entanto, se em vez de fundição, eu saída o flutuador como uma string, e analisar a cadeia como um duplo, recebo o que eu quero:

System.out.println(Double.toString(Double.parseDouble(Float.toString(temp))));
// Prints 14009.35

Existe uma maneira melhor do que ir para String e volta?

Foi útil?

Solução

Não é que você está realmente obter maior precisão - é que o flutuador não representar com precisão o número que estavam apontando para originalmente. A dupla é que representa o flutuador originais com precisão; toString está mostrando os dados "extra" que já estava presente.

Por exemplo (e estes números não estão bem, eu só estou fazendo as coisas) suponha que você tinha:

float f = 0.1F;
double d = f;

Em seguida, o valor de f pode ser exatamente 0,100000234523. d terá exatamente o mesmo valor, mas quando você convertê-lo em uma corda que vai "confiança" de que é preciso para uma precisão superior, fora por isso não vai rodada tão cedo, e você verá os dígitos "extras" que foram já está lá, mas escondido de você.

Quando você converte em uma string e volta, você está terminando com um valor duplo que é mais perto do valor da cadeia do que o flutuador original - mas isso é apenas boa se Você realmente acredita que o valor da cadeia é o que você realmente queria.

Você tem certeza que float / double são os tipos apropriados para usar aqui em vez de BigDecimal? Se você está tentando usar números que têm valores decimais precisas (por exemplo, dinheiro), então BigDecimal é um tipo mais apropriado IMO.

Outras dicas

Acho conversão para a representação binária mais fácil de entender este problema.

float f = 0.27f;
double d2 = (double) f;
double d3 = 0.27d;

System.out.println(Integer.toBinaryString(Float.floatToRawIntBits(f)));
System.out.println(Long.toBinaryString(Double.doubleToRawLongBits(d2)));
System.out.println(Long.toBinaryString(Double.doubleToRawLongBits(d3)));

Você pode ver a bóia é expandida para o dobro, adicionando 0s até o fim, mas que a dupla representação de 0,27 é 'mais precisa', daí o problema.

   111110100010100011110101110001
11111111010001010001111010111000100000000000000000000000000000
11111111010001010001111010111000010100011110101110000101001000

Isto é devido ao contrato de Float.toString(float), que diz em parte:

quantos dígitos devem ser impressos para a parte fracionária [...]? Lá deve ter pelo menos um dígito representam a parte fracionária, e além de que, como muitos, , mas apenas como muitos, mais dígitos como são necessários para singularmente distinguir o valor do argumento de valores adjacentes do tipo float. Isso é, suponha que x é a exata valor matemático representado pelo representação decimal produzido pela este método para um diferente de zero finito argumento f. Então f deve ser o flutuador valor mais próximo de x; ou, se dois flutuador Os valores são igualmente perto de X, então f deve ser um deles e os menos pouco significativa do significando de f deve ser 0.

Eu encontrei esta questão hoje e não poderia usar refactor para BigDecimal, porque o projeto é realmente enorme. No entanto eu encontrei solução usando

Float result = new Float(5623.23)
Double doubleResult = new FloatingDecimal(result.floatValue()).doubleValue()

e isso funciona.

Note que chamar result.doubleValue () retorna 5.623,22998046875

Mas chamar doubleResult.doubleValue () retorna corretamente 5.623,23

Mas eu não sou inteiramente certo se é uma solução correta.

Use um BigDecimal vez de float / double. Há uma série de números que não podem ser representados como ponto binário flutuante (por exemplo, 0.1). Então, você quer sempre deve arredondar o resultado com uma precisão ou uso BigDecimal conhecido.

Consulte http://en.wikipedia.org/wiki/Floating_point para mais informações .

Eu encontrei o seguinte solução:

public static Double getFloatAsDouble(Float fValue) {
    return Double.valueOf(fValue.toString());
}

Se você usar flutuador e duplo em vez de Float e duplo use o seguinte:

public static double getFloatAsDouble(float value) {
    return Double.valueOf(Float.valueOf(value).toString()).doubleValue();
}

flutua, por natureza, são imprecisos e sempre ter arrumado arredondamento "questões". Se a precisão é importante, então você pode considerar refatoração seu aplicativo para uso Decimal ou BigDecimal.

Sim, flutuadores são computacionalmente mais rápido do que os decimais por causa da sobre o suporte do processador. No entanto, você quer rápido ou preciso?

Para obter informações isto vem sob o Item 48 - Evite float e double quando valores exatos são necessários, de Effective Java 2ª edição por Joshua Bloch. Este livro é atolamento embalado com coisas boas e olhar uma definitivamente vale a pena.

Será que este trabalho?

float flt = 145.664454;

Double dbl = 0.0;
dbl += flt;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top