¿Cuándo tiene sentido en la programación probar la igualdad de dos números de coma flotante?
es decir
a == b
donde tanto a & b son flotadores.
Mi ingenua impresión es que uno siempre probaría la diferencia contra alguna tolerancia épsilon.
¿Me equivoco? ¿Puede probar la igualdad de las carrozas ser significativo en ciertos contextos?
¿Algún ejemplo de la naturaleza? es decir, desde bases de código reales o aplicaciones disponibles en git, etc.
PD. Estoy implícitamente asumiendo que usar el operador de igualdad en flotadores es realmente significativo en algunos contextos; de lo contrario, ¿por qué la mayoría de los lenguajes de programación lo permitirían?
floating-point
curioso_cat
fuente
fuente
Respuestas:
Una implementación no ingenua de esta idea probablemente debería aprovechar el operador de comparación de igualdad para manejar los casos especiales importantes que contempla el estándar IEEE 754 (infinitos, números desnormalizados ...).
Echa un vistazo a ¿Cómo debo hacer la comparación de punto flotante? :
A veces realmente hay una respuesta que es correcta y quieres igualdad exacta. Probar la exactitud de una implementación es un buen ejemplo (es decir , solo hay cuatro mil millones de flotadores, ¡así que pruébelos a todos! ).
fuente
Un ejemplo obvio donde
==
está bien, es cuandoa
yb
es el mismo es decir, númeroa=c; b=c
, por ejemplo para verificar sia
yb
se inicializa la misma manera. Por supuesto,|a-b| < epsilon
también funcionaría aquí. El único problema es, ¿qué tan pequeño esepsilon
?Además,
a == b
se compilaría en una sola instrucción, mientras|a-b| < epsilon
que tomaría bastantes.fuente
for x in [0..n] step w: for y in [0..n] step w: add_tile(x, y)
. En ese caso,t1.x == t2.x
es una forma perfectamente segura de probar si las dos fichas están en un plano. Solo necesita|a-b|<epsilon
cuándoa
yb
son resultados de diferentes cálculos que supuestamente obtendrían el mismo valor. Pero muy a menudo tiene un resultado de un cálculo almacenado en dos variables, o sobrescribe variables con constantes.Un ejemplo extremo: IBM fue la primera compañía que construyó procesadores con una instrucción fusionada de adición múltiple. Utilizando esa instrucción, crearon un método muy rápido para calcular raíces cuadradas de acuerdo con el estándar IEEE-754. Este método falla para un solo valor de entrada 1 ≤ x <4: si x es el número más grande representable como un número de coma flotante que es menor que 4, entonces el resultado se redondeará incorrectamente.
Entonces, en algún lugar de su implementación, verifican si x es igual a ese valor específico. Quieren reconocer ese valor, y no otros.
fuente
No hay recetas únicas. En este artículo hay un tratamiento exhaustivo, donde puede encontrar una respuesta completa con código técnico y.
En resumen, hay principalmente 3 casos:
Su idea de usar una comparación contra una tolerancia es buena para algunos casos, pero también hay una técnica basada en la Unidad en último lugar ( ULP ), descrita en el artículo.
Como anteriormente, hay situaciones en las que puede usarlo, pero tenga cuidado. Por ejemplo, el compilador gcc tiene una advertencia:
Actualizar
Agrego algunas consideraciones sobre este argumento y tampoco están estrictamente relacionadas con el caso
a == b
.Igualdad con expresión
Considerando el caso:
a b c
Entonces, en este caso, el uso de
==
es más delicado.Portado en diferentes ambientes
Cuando portamos un código en diferentes entornos (máquina diferente) podemos obtener un resultado diferente (por ejemplo, tratar de pensar en una prueba unitaria). También en el caso el uso de
==
es delicado.fuente
Su "impresión ingenua" no es una "impresión ingenua": es el resultado de leer sobre aritmética de coma flotante y solo comprenderla a medias. La "impresión ingenua" sería la impresión obvia de que para saber si a y b son iguales, se pregunta si son iguales.
Hay muchas situaciones en las que todo lo que necesita saber es si dos números de coma flotante son iguales o no. Hay muchas situaciones en las que sabe que no hay errores de redondeo o que no hay variaciones debido a errores de redondeo. Como convertir números decimales a coma flotante, que será determinista en cualquier implementación sensata.
Aquí hay una buena: alguien afirmó que para cualquiera de los dos números de coma flotante a, b, el resultado de (b + a + b) y (b + b + a) es el mismo y desea probar esa afirmación. Intenta hacerlo sin comparar dos números de coma flotante para la igualdad.
Aquí hay uno mejor: intente crear un conjunto de números de coma flotante.
fuente
Consulte esta pregunta: /cs/19013/is-transitivity-required-for-a-sorting-algorithm?rq=1
Explica muy bien cómo la comparación de coma flotante con algunos epsilon puede conducir a una falla completa y total del algoritmo de clasificación rápida.
fuente