Why does Double.NaN==Double.NaN return false?

2020-01-23 07:20发布

I was just studying OCPJP questions and I found this strange code:

public static void main(String a[]) {
    System.out.println(Double.NaN==Double.NaN);
    System.out.println(Double.NaN!=Double.NaN);
}

When I ran the code, I got:

false
true

How is the output false when we're comparing two things that look the same as each other? What does NaN mean?

9条回答
仙女界的扛把子
2楼-- · 2020-01-23 07:34

NaN is by definition not equal to any number including NaN. This is part of the IEEE 754 standard and implemented by the CPU/FPU. It is not something the JVM has to add any logic to support.

http://en.wikipedia.org/wiki/NaN

A comparison with a NaN always returns an unordered result even when comparing with itself. ... The equality and inequality predicates are non-signaling so x = x returning false can be used to test if x is a quiet NaN.

Java treats all NaN as quiet NaN.

查看更多
我命由我不由天
3楼-- · 2020-01-23 07:35

NaN means "Not a Number".

Java Language Specification (JLS) Third Edition says:

An operation that overflows produces a signed infinity, an operation that underflows produces a denormalized value or a signed zero, and an operation that has no mathematically definite result produces NaN. All numeric operations with NaN as an operand produce NaN as a result. As has already been described, NaN is unordered, so a numeric comparison operation involving one or two NaNs returns false and any != comparison involving NaN returns true, including x!=x when x is NaN.

查看更多
Root(大扎)
4楼-- · 2020-01-23 07:35

The javadoc for Double.NaN says it all:

A constant holding a Not-a-Number (NaN) value of type double. It is equivalent to the value returned by Double.longBitsToDouble(0x7ff8000000000000L).

Interestingly, the source for Double defines NaN thus:

public static final double NaN = 0.0d / 0.0;

The special behaviour you describe is hard-wired into the JVM.

查看更多
放荡不羁爱自由
5楼-- · 2020-01-23 07:36

Not a number represents the result of operations whose result is not representable with a number. The most famous operation is 0/0, whose result is not known.

For this reason, NaN is not equal to anything (including other not-a-number values). For more info, just check the wikipedia page: http://en.wikipedia.org/wiki/NaN

查看更多
放荡不羁爱自由
6楼-- · 2020-01-23 07:42

as per, The IEEE standard for floating point arithmetic for Double Precision numbers,

The IEEE double precision floating point standard representation requires a 64 bit word, which may be represented as numbered from 0 to 63, left to right

enter image description here where,

S: Sign – 1 bit
E: Exponent – 11 bits
F: Fraction – 52 bits 

If E=2047 (all E are 1) and F is nonzero, then V=NaN ("Not a number")

Which means,

If all E bits are 1, and if there is any non-zero bit in F then the number is NaN.

therefore, among others, all following numbers are NaN,

0 11111111 0000000000000000010000000000000000000000000000000000 = NaN
1 11111111 0000010000000000010001000000000000001000000000000000 = NaN
1 11111111 0000010000011000010001000000000000001000000000000000 = NaN

In particular, you cannot test

if (x == Double.NaN) 

to check whether a particular result equals Double.NaN, because all “not a number” values are considered distinct. However, you can use the Double.isNaN method:

if (Double.isNaN(x)) // check whether x is "not a number"
查看更多
一纸荒年 Trace。
7楼-- · 2020-01-23 07:45

It might not be a direct answer to the question. But if you want to check if something is equal to Double.NaN you should use this:

double d = Double.NaN
Double.isNaN(d);

This will return true

查看更多
登录 后发表回答