Eu estava apenas estudando questões da OCPJP e encontrei esse código estranho:
public static void main(String a[]) {
System.out.println(Double.NaN==Double.NaN);
System.out.println(Double.NaN!=Double.NaN);
}
Quando executei o código, obtive:
false
true
Como está o resultado false
quando comparamos duas coisas que parecem iguais? O que NaN
significa isso ?
In [1]: NaN==NaN Out[1]: False
Double.NaN==Double.NaN
deve realmente retornar true seDouble.NaN
fosse do tipojava.lang.Double
. No entanto, seu tipo é o primitivodouble
, e as regras do operador paradouble
aplicação (que exigem essa desigualdade por conformidade com o IEEE 754, conforme explicado nas respostas).Respostas:
NaN significa "Não é um número".
A terceira edição da Java Language Specification (JLS) diz :
fonte
false
. Portanto, esse padrão difere do Java, pois o IEEE exige isso(NAN != NAN) == false
.NaN, por definição, não é igual a qualquer número, incluindo NaN. Isso faz parte do padrão IEEE 754 e implementado pela CPU / FPU. Não é algo que a JVM precise adicionar lógica para suportar.
http://en.wikipedia.org/wiki/NaN
Java trata todo NaN como NaN silencioso.
fonte
Por que essa lógica
NaN
meiosNot a Number
. O que não é um número? Qualquer coisa. Você pode ter qualquer coisa de um lado e qualquer coisa do outro lado; portanto, nada garante que ambos sejam iguais.NaN
é calculado comDouble.longBitsToDouble(0x7ff8000000000000L)
e como você pode ver na documentação delongBitsToDouble
:Além disso,
NaN
é tratado logicamente dentro da API.Documentação
A propósito,
NaN
é testado como seu exemplo de código:Solução
O que você pode fazer é usar
compare
/compareTo
:Ou
equals
:fonte
NaN != NaN
ser falso tornaria os programas mais complicados do queNaN != NaN
verdadeiros? Sei que o IEEE tomou a decisão há muito tempo, mas, de uma perspectiva prática, nunca vi casos em que isso fosse útil. Se uma operação for executada até que iterações consecutivas produzam o mesmo resultado, ter duas iterações consecutivas produzindo NaN seria "naturalmente" detectado como uma condição de saída, não fosse por esse comportamento.f(f(f...f(x)))
, e encontrar umy=f[n](x)
para alguns den
modo que o resultado def(y)
seja indistinguível dey
, entãoy
será indistinguível do resultado de qualquer aninhamento mais profundof(f(f(...f(y)))
. Mesmo se alguém quisesseNaN==NaN
ser falso,Nan!=Nan
também ser falso seria menos "surpreendente" do quex!=x
ser verdadeiro para alguns x.Double.NaN
não éDouble
, masdouble
, então a questão é uma relacionada ao comportamento dedouble
. Embora existam funções que podem testar uma relação de equivalência envolvendodouble
valores, a única resposta convincente que conheço para "por que" (que faz parte da pergunta original) é "porque algumas pessoas no IEEE não acharam que o teste de igualdade deveria defina uma relação de equivalência ". BTW, existe alguma maneira idiomática concisa de testarx
ey
equivalência usando apenas operadores primitivos? Todas as formulações que conheço são bastante desajeitadas.Pode não ser uma resposta direta à pergunta. Mas se você quiser verificar se algo é igual a
Double.NaN
você, use este:Isso retornará
true
fonte
O javadoc para Double.NaN diz tudo:
Curiosamente, a fonte para
Double
defineNaN
assim:O comportamento especial que você descreve é conectado à JVM.
fonte
conforme o padrão IEEE para aritmética de ponto flutuante para números de precisão dupla,
Onde,
Que significa,
Se todos os
E
bits forem 1 e se houver um bit diferente de zeroF
, o número seráNaN
.portanto, entre outros, todos os números a seguir são
NaN
,Em particular, você não pode testar
para verificar se um resultado específico é igual
Double.NaN
, porque todos os valores "não são números" são considerados distintos. No entanto, você pode usar oDouble.isNaN
método:fonte
NaN é um valor especial que indica "não é um número"; é o resultado de certas operações aritméticas inválidas, como
sqrt(-1)
, e possui a propriedade (às vezes irritante) dissoNaN != NaN
.fonte
Nenhum número representa o resultado de operações cujo resultado não é representável com um número. A operação mais famosa é 0/0, cujo resultado não é conhecido.
Por esse motivo, NaN não é igual a nada (incluindo outros valores que não são um número). Para mais informações, basta verificar a página da wikipedia: http://en.wikipedia.org/wiki/NaN
fonte
0/0
.0/0
é sempre NaN, mas NaN pode ser o resultado de outras operações - como2+NaN
:an operation that has no mathematically definite result produces NaN
, conforme a resposta por @AdrianMitevDe acordo com este link , possui várias situações e difíceis de lembrar. É assim que eu me lembro e os distingo.
NaN
significa "matematicamente indefinido", por exemplo: "o resultado de 0 dividido por 0 é indefinido" e, como é indefinido, portanto "a comparação relacionada com o indefinido é obviamente indefinida". Além disso, funciona mais como premissas matemáticas. Por outro lado, tanto o infinito positivo quanto o negativo são predefinidos e definitivos, por exemplo "infinito positivo ou negativo grande é bem definido matematicamente".fonte