with comparing c ieee-754 comparison-operators

comparing - Casos donde float== y!=No son opuestos directos



compare floating point numbers c++ (2)

En https://github.com/numpy/numpy/issues/6428 , la causa raíz del error parece ser que en simd.inc.src:543 , ¡un compilador optimiza !(tmp == 0.) a tmp != 0. ..

Un comentario dice que estos "no son exactamente lo mismo". Pero no especifica ningún detalle. Los NaN se mencionan más adelante, pero una prueba muestra que un NaN se compara con 0. la forma esperada.

¿Cuáles son los casos en que == y != Pueden ambos devolver verdadero / falso?

O la discrepancia está en otro campo , por ejemplo, valores de retorno que tienen el mismo valor de verdad pero son diferentes a los ints (pero las pruebas muestran que incluso esto no parece ser el caso) .


Un comentario dice que estos "no son exactamente lo mismo". Pero no especifica ningún detalle. Los NaN se mencionan más adelante, pero una prueba muestra que un NaN se compara con 0. la forma esperada.

¿Cuáles son los casos en que == y! = Pueden ambos devolver verdadero / falso?

La norma dice:

Los operadores == (iguales a) y != (No iguales a) son análogos a los operadores relacionales a excepción de su precedencia inferior. [...] Para cualquier par de operandos, exactamente una de las relaciones es verdadera.

(C2011, 6.5.9 / 3; énfasis añadido)

Por lo tanto, para cualquier expresión X e Y que se permitan conjuntamente como operandos de estos operadores, (X) != (Y) debe evaluar el mismo resultado que !((X) == (Y)) . Si en la práctica se encuentra que no lo hacen, entonces el compilador que produjo ese resultado no es conforme a ese respecto. Si esa no conformidad es inesperada, entonces constituye un error en el compilador.

Además, observo que 6.5.9 / 3 se aplica tanto a NaNs, infinitos y subnormales como a cualquier otro operando. Los NaN son especiales con respecto a estos operadores por una razón diferente: los NaN se comparan de forma desigual con todos los operandos, incluidos ellos mismos (suponiendo la semántica IEEE).


Desde el post vinculado:

charris comentó el 9 de oct de 2015

Voy a adivinar que !(tmp == 0.) está optimizado para tmp != 0. , que no es exactamente lo mismo.

Comentario del OP:

El autor dice que es una conjetura, pero están bastante seguros de que !(tmp==0.) Y tmp!=0. No son equivalentes y expresan eso como si fuera conocimiento común.

¿Cómo reconciliar estos dos?

Claramente, son lógicamente equivalentes. Pero en cuanto a la implementación, pueden no serlo. Un compilador podría implementar !(a == b) como la prueba a == b seguido de una negación. Alternativamente, podría optimizar la expresión y probar directamente a != b El código de ensamblaje resultante sería diferente en esos dos casos. Se debe (debe) lograr el mismo resultado, pero el tiempo de ejecución podría ser diferente.

"no es exactamente lo mismo" sería simplemente un reconocimiento de que !(a == b) y a != b son en realidad diferentes combinaciones de caracteres y el compilador podría hacer algo técnicamente diferente con ellos, que debe dar el mismo resultado. Y si se observan resultados diferentes, entonces podría existir un error en el compilador.