¿Por qué double.NaN no es igual a sí mismo?

82

¿Alguien puede explicarme esto? En C # double.NaN no es igual a double.NaN

bool huh = double.NaN == double.NaN; // huh = false
bool huh2 = double.NaN >= 0; // huh2 = false
bool huh3 = double.NaN <= 0; // huh3 = false

¿Qué constante puedo comparar con un double.NaN y volverme verdadera?

Carlo
fuente
12
Solo para explicar tus huhs: NaN es igual a nada, ni siquiera a sí mismo. Esto es por definición. en.wikipedia.org/wiki/NaN
Falaina
2
Lo que creo que es lamentable es que se pierde el contexto. Si tuviéramos dos dobles, y a ambos se les asignó un valor de NaN para representar el valor real 1/0. Deberían ser iguales, pero dado que se pierde el contexto, se les trata como no iguales
Michael Meadows
13
matemáticamente correcto. ¿Por qué uno pensaría que un nan sería igual a otro? sqrt (-1)! = 1/0
Gordon Gustafson
2
Es como NULLen SQL
shashwat
2
@MichaelMeadows 1/0 es Inf, no NaN.
Jim Balter

Respuestas:

133

Si tiene curiosidad, esto es lo que Double.IsNaNparece:

public static bool IsNaN(double d)
{
    return (d != d);
}

Funky, ¿eh?

Erich Mirabal
fuente
11
Eso es extraño, de acuerdo. Pero, de nuevo, también lo es la declaración de NaN:public const double NaN = (double) 1.0 / (double) 0.0;
Fredrik Mörk
5
@Fredik, @Erich: La división por cero dará inf (o, + inf, -inf según los operandos), 0/0 (entre otros) da como resultado un NaN. Hay una buena tabla con operaciones / resultados especiales en steve.hollasch.net/cgindex/coding/ieeefloat.html
Torsten Marek
5
Para aumentar la confusión, object.Equals (double.NaN, double.NaN) devuelve verdadero
Román
2
@JimBalter Tienes razón en que mi comentario estaba equivocado: la fuente de referencia en realidad dice public const double NaN = (double)0.0 / (double)0.0; enlace a la fuente de referencia . Gracias por señalar eso. En otra nota: estar equivocado y mentir son dos cosas completamente diferentes
Fredrik Mörk
1
No estoy seguro de si esto era correcto cuando lo publicó, pero IsNaN se define de manera diferente hoy.
Joe Amenta
16
bool isNaN = Double.IsNaN(yourNumber)
Francis B.
fuente
10

El comportamiento es a propósito. La razón por la que NaN representa algo que no es un número y, por lo tanto, es una especie de comodín para muchas cosas.

La forma correcta de comparar algo con ser NaN es usar el función IsNaN .

Mike Dinescu
fuente
7

Utilice Double.IsNan () para probar la igualdad aquí. La razón es que NaN no es un número.

Colin Mackay
fuente
6

Hay una función especializada para esto:

double.IsNan(huh);
arul
fuente
5

Utilice el método "Double.IsNaN (valor)" para comprobar esta condición.

David
fuente
3

En realidad, ya encontró la manera de verificar si un número de punto flotante IEEE-754 es NaN : es el único valor de punto flotante (o rango de valores, porque hay varios NaN) que evalúa Falsesi se compara con él mismo, es decir:

bool isNaN(double v) {
    return v != v;
}

Bajo el capó, el método Double.IsNaN en realidad podría hacer lo mismo. Aún debe usarlo, porque el comportamiento es bastante sorprendente para cualquiera que no conozca el estándar FP.

Torsten Marek
fuente
2

Lo único que sabemos sobre NaN es que "no es un número". Eso no significa que tenga un valor asociable a su estado. Por ejemplo:

∞ + (-∞) = NaN

0/0 = NaN

(∞ + (-∞)) <> (0/0)

Aquí hay algo de C # para demostrar

var infinity = 100d / 0;
var negInfinity = -100d / 0;

var notANumber = infinity + negInfinity;
Console.WriteLine("Negative Infinity plus Infinity is NaN: {0}", double.IsNaN(notANumber));

var notANumber2 = 0d / 0d;
Console.WriteLine("Zero divided by Zero is NaN: {0}", double.IsNaN(notANumber2));

Console.WriteLine("These two are not equal: {0}", notANumber == notANumber2);
Michael Meadows
fuente
2

La razón Double.NaN != Double.NaNes simple:

¿Esperas 0/0ser igual que Math.Sqrt(-3)? ¿Y lo mismo que Math.Sqrt(-7)?

Hay un error en C # en mi opinión donde Equals()no se anula para NaN.

Assert.IsTrue(Double.NaN != Double.NaN);
Assert.IsTrue(Double.NaN.Equals(Double.NaN));

Al mismo tiempo

Assert.IsTrue(Double.PositiveInfinity == Double.NegativeInfinity);
Assert.IsTrue(Double.PositiveInfinity.Equals(Double.PositiveInfinity));
// same for Double.NegativeInfinity and Single

Utilice funciones estáticas para Doubley Single, p. Ej.

Double.IsNaN(value) && Double.IsInfinity(value);

O más específico:

Double.IsPositiveInfinity(value);
Double.IsNegativeInfinity(value);
Artru
fuente
2

El operador de Igualdad considera que dos valores de NaN no son iguales entre sí. En general, los operadores Double no se pueden usar para comparar Double.NaN con otros valores Double, aunque los métodos de comparación (como Equals y CompareTo ) sí pueden. ver ejemplos a continuación

Referenciado de msdn

class Program
{
    static void Main(string[] args)
    {
        Double i = Double.NaN;
        while (!i.Equals(i)) //this would be result in false
        //while(i != i) // this would result in true.
        {
            Console.WriteLine("Hello");
        }
    }
}

aquí está .net violín para el mismo.

Jenish Rabadiya
fuente