2010-09-13 11 views
6

Si comparo dos números de coma flotante, hay casos en los que a>=b no es equivalente a b<=a y !(a<b), o cuando a==b no es equivalente a b==a y !(a!=b)?¿Hay alguna "anomalía" de comparación en coma flotante?

En otras palabras: ¿las comparaciones son siempre "simétricas", de modo que puedo obtener el mismo resultado en una comparación al intercambiar los operandos y duplicar el operador? ¿Y son siempre "negables", de modo que negar a un operador (por ejemplo, > a <=) es equivalente a aplicar un NOT lógico (!) al resultado?

+0

Agregué un segundo párrafo para aclarar mi pregunta. Según la respuesta aceptada, parecería que son "simétricos" pero no "negables" debido a los NaN. – mwfearnley

Respuesta

7

Suponiendo IEEE-754 de coma flotante:

  • a >= b siempre es equivalente a b <= a *
  • a >= b es equivalente a !(a < b), a menos que uno o ambos de a o b es NaN..
  • a == b siempre es equivalente a b == a. *
  • a == b es equivalente a !(a != b), a menos que uno o ambos de a o b es NaN.

De manera más general: tricotomía no se mantiene para los números de punto flotante. En lugar de ello, una propiedad relacionada sostiene [IEEE-754 (1985) §5.7]:

Cuatro relaciones mutuamente exclusivos son posibles: menor que, igual, mayor que, y no ordenada. El último caso surge cuando al menos un operando es NaN. Cada NaN debe comparar desordenado con todo, incluido él mismo.

Tenga en cuenta que esto no es realmente una "anomalía" tanto como consecuencia de la ampliación de la aritmética que ser cerrado de manera que los intentos de mantener la coherencia con la aritmética real cuando sea posible.

[*] true en aritmética abstracta IEEE-754. En el uso real, algunos compiladores pueden hacer que esto se viole en casos raros como resultado de hacer cálculos con precisión extendida (MSVC, te estoy mirando). Ahora que la mayoría del cálculo de coma flotante en la arquitectura Intel se realiza en SSE en lugar de x87, esto es menos preocupante (y siempre fue un error desde el punto de vista de IEEE-754, de todos modos).

1

No, no para una implementación sana de punto flotante: se aplica la simetría básica y la lógica booleana. Sin embargo, equality in floating point numbers es complicado de otras maneras. Hay muy pocos casos donde la prueba de a==b para flotadores es lo razonable.

3

En Python al menos a>=b no es equivalente a !(a<b) cuando hay un NaN involucrado:

>>> a = float('nan') 
>>> b = 0 
>>> a >= b 
False 
>>> not (a < b) 
True 

Me imagino que este es también el caso en la mayoría de los otros idiomas.

Otra cosa que puede sorprender es que NaN ni siquiera comparar igual a sí mismo:

>>> a == a 
False 
+2

+1: Cualquier sistema que use coma flotante IEEE tendrá este comportamiento extraño (o generará excepciones para producir un valor tan erróneo; después de todo, indicará dónde ha ido mal la aritmética, como el resultado de dividir 0.0 por 0.0). –

3

El conjunto de IEEE-754 números de punto flotante no están ordenados de manera un poco de álgebra relacional y booleano está familiar con ya no se sostiene. Esta anomalía es causada por NaN, que no tiene orden con respecto a ningún otro valor en el conjunto, incluido él mismo, por lo que todos los operadores relacionales devuelven falso. Esto es exactamente lo que Mark Byers ha demostrado.

Si excluye NaN, entonces ahora tiene un conjunto ordenado y las expresiones que proporcionó siempre serán equivalentes. Esto incluye los infinitos y el cero negativo.

2

Aparte del problema NaN, que es algo análogo a NULL en SQL y valores perdidos en SAS y otros paquetes estadísticos, siempre existe el problema de la precisión aritmética de coma flotante. La repetición de valores en la parte fraccional (1/3, por ejemplo) y los números irracionales no se pueden representar con precisión. El aritmático de coma flotante a menudo trunca los resultados debido al límite finito de precisión. Cuanto más arithematic que se hace con un valor de punto flotante, cuanto mayor sea el error que se arrastra en

Probablemente la forma más útil para comparar los valores de punto flotante sería con un algoritmo:.

  1. Si cualquiera de los valores es NaN , todas las comparaciones son falsas, a menos que esté comprobando explícitamente NaN.
  2. Si la diferencia entre dos números está dentro de un cierto "factor de fuzz", considérelos iguales. El factor de fuzz es su tolerancia a la imprecisión matemática acumulada.
  3. Después de la comparación de igualdad difusa, compárela por menos de o mayor que.

Tenga en cuenta que comparar para "< =" o "> =" tiene el mismo riesgo que la comparación para una igualdad precisa.

Cuestiones relacionadas