igualdad de coma flotante en Python y en general
Tengo un código que se comporta de manera diferente dependiendo de si reviso un diccionario para obtener factores de conversión o si los uso directamente.
Se imprimirá el siguiente código1.0 == 1.0 -> False
Pero si reemplazasfactors[units_from]
con10.0
yfactors[units_to ]
con1.0 / 2.54
imprimirá1.0 == 1.0 -> True
#!/usr/bin/env python
base = 'cm'
factors = {
'cm' : 1.0,
'mm' : 10.0,
'm' : 0.01,
'km' : 1.0e-5,
'in' : 1.0 / 2.54,
'ft' : 1.0 / 2.54 / 12.0,
'yd' : 1.0 / 2.54 / 12.0 / 3.0,
'mile' : 1.0 / 2.54 / 12.0 / 5280,
'lightyear' : 1.0 / 2.54 / 12.0 / 5280 / 5.87849981e12,
}
# convert 25.4 mm to inches
val = 25.4
units_from = 'mm'
units_to = 'in'
base_value = val / factors[units_from]
ret = base_value * factors[units_to ]
print ret, '==', 1.0, '->', ret == 1.0
Permítanme decir primero que estoy bastante seguro de lo que está pasando aquí. Lo he visto antes en C, simplemente nunca en Python, pero desde Python implementado en C lo estamos viendo.
Sé que los números de coma flotante cambiarán los valores que van de un registro de CPU a caché y viceversa. Sé que comparar lo que deberían ser dos variables iguales devolverá falso si una de ellas fue paginada mientras la otra permaneció residente en un registro.
Preguntas
¿Cuál es la mejor manera de evitar problemas como este? ... En Python o en general.¿Estoy haciendo algo completamente mal?Nota al margen
Obviamente, esto es parte de un ejemplo simplificado, pero lo que intento hacer es venir con clases de longitud, volumen, etc. que se puedan comparar con otros objetos de la misma clase pero con unidades diferentes.
Preguntas retóricas
Si este es un problema potencialmente peligroso, ya que hace que los programas se comporten de manera poco realista, los compiladores deben advertir o cometer un error cuando detectan que está comprobando la igualdad de los flotadores¿Deberían los compiladores admitir una opción para reemplazar todas las comprobaciones de igualdad flotante con una función 'lo suficientemente cercana'?Los compiladores ya hacen esto y simplemente no puedo encontrar la información.