Estaba estudiando preguntas de OCPJP y encontré este código extraño:
public static void main(String a[]) {
System.out.println(Double.NaN==Double.NaN);
System.out.println(Double.NaN!=Double.NaN);
}
Cuando ejecuté el código, obtuve:
false
true
¿Cómo es la salida false
cuando estamos comparando dos cosas que se parecen entre sí? Que NaN
significa
In [1]: NaN==NaN Out[1]: False
Double.NaN==Double.NaN
debería volver verdadero siDouble.NaN
fueran de tipojava.lang.Double
. Sin embargo, su tipo es el primitivodouble
, y las reglas del operador paradouble
aplicar (que exigen esta desigualdad para cumplir con IEEE 754, como se explica en las respuestas).Respuestas:
NaN significa "No es un número".
Java Language Specification (JLS) Third Edition dice :
fuente
false
. Entonces, ese estándar difiere de Java en que IEEE lo exige(NAN != NAN) == false
.NaN no es, por definición, igual a ningún número, incluido NaN. Esto es parte del estándar IEEE 754 e implementado por la CPU / FPU. No es algo a lo que la JVM tenga que agregar ninguna lógica para soportar.
http://en.wikipedia.org/wiki/NaN
Java trata todo NaN como NaN silencioso.
fuente
¿Por qué esa lógica?
NaN
significaNot a Number
. ¿Qué no es un número? Cualquier cosa. Puede tener cualquier cosa en un lado y cualquier cosa en el otro lado, por lo que nada garantiza que ambos sean iguales.NaN
se calcula conDouble.longBitsToDouble(0x7ff8000000000000L)
y como puede ver en la documentación delongBitsToDouble
:Además,
NaN
se trata lógicamente dentro de la API.Documentación
Por cierto,
NaN
se prueba como muestra de código:Solución
Lo que puedes hacer es usar
compare
/compareTo
:O
equals
:fuente
NaN != NaN
ser falso haría que los programas sean más complicados queNaN != NaN
ser cierto? Sé que IEEE tomó la decisión hace mucho tiempo, pero desde una perspectiva práctica, nunca he visto casos en los que sea útil. Si se supone que una operación se ejecuta hasta que las iteraciones consecutivas produzcan el mismo resultado, tener dos iteraciones consecutivas produce NaN se detectaría "naturalmente" como una condición de salida si no fuera por ese comportamiento.f(f(f...f(x)))
, y encuentra unoy=f[n](x)
para algunos de losn
cuales el resultado def(y)
es indistinguibley
, entoncesy
será indistinguible del resultado de cualquier anidamiento más profundof(f(f(...f(y)))
. Incluso si uno quisieraNaN==NaN
ser falso, tenerloNan!=Nan
también sería menos "sorprendente" quex!=x
ser cierto para algunas x.Double.NaN
no lo esDouble
, perodouble
la pregunta está relacionada con el comportamiento dedouble
. Aunque existen funciones que pueden evaluar una relación de equivalencia que involucradouble
valores, la única respuesta convincente que conozco para "por qué" (que es parte de la pregunta original) es "porque algunas personas en el IEEE no pensaron que la prueba de igualdad debería definir una relación de equivalencia ". Por cierto, ¿hay alguna forma idiomática concisa de probarx
yy
para la equivalencia usando solo operadores primitivos? Todas las formulaciones que conozco son bastante torpes.Puede que no sea una respuesta directa a la pregunta. Pero si desea verificar si algo es igual a esto
Double.NaN
, debe usar esto:Esto volverá
true
fuente
El javadoc para Double.NaN lo dice todo:
Curiosamente, la fuente de
Double
defineNaN
así:El comportamiento especial que describe está conectado a la JVM.
fuente
según, el estándar IEEE para aritmética de coma flotante para números de doble precisión,
dónde,
Lo que significa,
Si todos los
E
bits son 1, y si hay algún bit distinto de cero,F
entonces el número esNaN
.por lo tanto, entre otros, todos los siguientes números son
NaN
,En particular, no puedes probar
para verificar si un resultado particular es igual
Double.NaN
, porque todos los valores "no un número" se consideran distintos. Sin embargo, puede usar elDouble.isNaN
método:fuente
NaN es un valor especial que denota "no un número"; es el resultado de ciertas operaciones aritméticas no válidas, como
sqrt(-1)
, y tiene la propiedad (a veces molesta) queNaN != NaN
.fuente
Ningún número representa el resultado de operaciones cuyo resultado no es representable con un número. La operación más famosa es 0/0, cuyo resultado no se conoce.
Por esta razón, NaN no es igual a nada (incluidos otros valores que no sean un número). Para obtener más información, solo consulte la página de Wikipedia: http://en.wikipedia.org/wiki/NaN
fuente
0/0
.0/0
siempre es NaN, pero NaN puede ser el resultado de otras operaciones, como2+NaN
:an operation that has no mathematically definite result produces NaN
según la respuesta de @AdrianMitevSegún este enlace , tiene varias situaciones y es difícil de recordar. Así es como los recuerdo y los distingo.
NaN
significa "matemáticamente indefinido", por ejemplo: "el resultado de 0 dividido por 0 es indefinido" y porque es indefinido, entonces "la comparación relacionada con indefinido es, por supuesto, indefinida". Además, funciona más como premisas matemáticas. Por otro lado, tanto el infinito positivo como el negativo están predefinidos y son definitivos, por ejemplo, "infinito positivo o negativo grande está bien definido matemáticamente".fuente