java - programacion - punto flotante ieee 754
¡Además de puntos flotantes, dando resultados extraños! (4)
Al ejecutar el siguiente código:
public class FPoint {
public static void main(String[] args) {
float f = 0.1f;
for(int i = 0; i<9; i++) {
f += 0.1f;
}
System.out.println(f);
}
}
Se muestra el siguiente resultado:
1.0000001
Pero la salida debería ser 1.0000000 , ¿verdad? Corrígeme si estoy equivocado..!!
0.1 no es realmente "0.1" con IEEE 754 Standard.
0.1 está codificado: 0 01111011 10011001100110011001101
(con número flotante)
- 0 es el signo (= positivo)
- 01111011 el exponente (= 123 -> 123 - 127 = -4 (127 es el sesgo en IEEE 754))
- 10011001100110011001101 la mantisa
Para convertir la mantisa en número decimal, tenemos 1.10011001100110011001101 * 2 ^ -4 (base2) [el 1.xxx está implícito en IEEE 754]
= 0.000110011001100110011001101 (base2)
= 1/2 ^ 4 + 1/2 ^ 5 + 1/2 ^ 8 + 1/2 ^ 9 + 1/2 ^ 12 + 1/2 ^ 13 + 1/2 ^ 16 + 1/2 ^ 17 + 1 / 2 ^ 20 + 1/2 ^ 21 + 1/2 ^ 24 + 1/2 ^ 25 + 1/2 ^ 27 (base10)
= 1/16 + 1/32 + 1/256 + 1/512 + 1/4096 + 1/8192 + 1/65536 + 1/131072 ... (base10)
= 0.10000000149011612 (base10)
Al igual que ciertos números reales como 1/3 no se pueden expresar exactamente en nuestro sistema decimal, ciertos números como 1/10 no se pueden expresar exactamente en binario.
1/3=(decimal)0.33333333333 (3) recurring
1/10=(binary)0.00011001100 (1100) recurring
Debido a que estamos tan familiarizados con el decimal, parece obvio que 1/3 no se puede representar exactamente, pero para alguien con un sistema numérico de base 3 esto parecería una limitación importante para el decimal;
1/3=(base 3)0.1
Como tal, 1/10 está inexactamente representado dentro del flotador y al sumar múltiples números inexactos se obtiene una respuesta inexacta.
Es en este contexto que debe interpretar los errores de coma flotante. Si tiene un número que es exactamente representable dentro de un decimal pero no dentro del binario, entonces puede encontrar que BigDecimal es útil. Pero no debes considerar que BigDecimal es mejor que los números de punto flotante; solo tiene un conjunto diferente de números que puede y no puede representar exactamente; el conjunto al que estás acostumbrado BigDecimal también intenta usar el sistema de conteo decimal en un procesador binario; como tal, sus cálculos son menos eficientes que los cálculos basados en doble / flotante
Es un malentendido común. Este tipo de "errores" están relacionados con las estructuras de datos de coma flotante: léelo. Puede usar un double
en este caso para obtener más precisión.
Si necesita un cálculo exacto, como cuando trabaja con datos muy confidenciales, no use float
o double
, su representación en binary uses approximations. Consulte este artículo para obtener algunas buenas explicaciones.