Pregunta

Tengo un flotador primitiva y necesito como un doble primitiva. Simplemente echando el flotador para duplicar me da rara precisión adicional. Por ejemplo:

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

Sin embargo, si en lugar de fundición, que la salida del flotador como una cadena, y analizar la cadena como un doble, consigo lo que quiero:

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

¿Hay una manera mejor que ir a la cuerda y la espalda?

¿Fue útil?

Solución

No es que eres realmente conseguir precisión adicional - es que el flotador no representa con precisión el número al que se proponían originalmente. La doble es que representa el flotador original con exactitud; toString está mostrando los datos "extra", que ya estaba presente.

Por ejemplo (y estos números no son correctas, sólo estoy haciendo las cosas) supongamos que tiene:

float f = 0.1F;
double d = f;

A continuación, el valor de f podría ser exactamente ,100000234523. d tendrá exactamente el mismo valor, pero cuando se convierte en una cadena que lo hará "confianza" que es preciso para una mayor precisión, por lo que no va a terminar tan temprano, y verá los dígitos adicionales "que eran" ya allí, pero oculto.

Cuando se convierte en una cadena y vuelta, que está terminando con un valor doble, que está más cerca del valor de cadena que el flotador original - pero eso es sólo es bueno si que realmente creen que el valor de cadena es lo que realmente quería.

¿Está seguro que flotan / doble son los tipos adecuados para usar aquí en lugar de BigDecimal? Si usted está tratando de utilizar los números que tienen valores decimales exactos (por ejemplo, dinero), entonces BigDecimal es un tipo más apropiado de la OMI.

Otros consejos

Me parece convertir a la representación binaria más 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)));

Se puede ver que el flotador se expande al doble mediante la adición de 0s a la final, pero que el doble representación de 0,27 es 'más precisa', por lo tanto el problema.

   111110100010100011110101110001
11111111010001010001111010111000100000000000000000000000000000
11111111010001010001111010111000010100011110101110000101001000

Esto es debido al contrato de Float.toString(float), que dice en parte:

  

¿Cuántos dígitos debe ser impreso para   la parte fraccionaria [...]? Ahí   debe ser por lo menos un dígito a   representar la parte fraccionaria, y   más allá de que, como muchos, pero sólo como muchos,    más dígitos que se necesitan para singularmente   distinguir el valor del argumento   valores adyacentes de tipo float. Que   Es decir, supongamos que x es la exacta   valor matemático representado por el   representación decimal producido por   este método para un distinto de cero finito   argumento f. Entonces f debe ser el flotador   valor más próximo a x; o, si dos de flotación   valores son igualmente cerca de x, entonces f   debe ser uno de ellos y la menor   poco significativo de la mantisa de   f debe ser 0.

Me he encontrado con este problema hoy y no podía usar refactor a BigDecimal, porque el proyecto es realmente enorme. Sin embargo he encontrado solución utilizando

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

Y esto funciona.

Tenga en cuenta que llamar result.doubleValue () devuelve 5623,22998046875

Pero llamar doubleResult.doubleValue () devuelve correctamente 5.623,23

Pero no estoy del todo seguro de si es una solución correcta.

Utilice un BigDecimal en lugar de float / double. Hay una gran cantidad de números que no pueden ser representados como punto binario flotante (por ejemplo, 0.1). Así que o bien debe siempre redondear el resultado con una precisión conocida o utilizar BigDecimal.

http://en.wikipedia.org/wiki/Floating_point para más información .

he encontrado la siguiente solución:

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

Si utiliza flotador y doble en lugar de Float y Doble utilizar lo siguiente:

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

Los flotadores, por naturaleza, son imprecisos y siempre tienen "problemas" ordenado redondeo. Si la precisión es importante, entonces usted podría considerar refactorización la aplicación para utilizar decimal o BigDecimal.

Sí, flotadores son computacionalmente más rápido que los decimales debido a la sobre soporte de procesadores. Sin embargo, ¿desea rápida o precisa?

Para obtener información esto viene en el Tema 48 - Evitar el flotador y el doble cuando se requieren valores exactos, de Effective Java 2ª edición por Joshua Bloch. Este libro está repleto de cosas buenas y una mirada definitivamente vale la pena.

¿Esto funciona?

float flt = 145.664454;

Double dbl = 0.0;
dbl += flt;
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top