[java] Double.NaN == Double.NaN이 false를 반환하는 이유는 무엇입니까?

방금 OCPJP 질문을 공부하고 있었고이 이상한 코드를 발견했습니다.

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

코드를 실행하면 다음과 같은 결과가 나타납니다.

false
true

어떻게 출력 false우리가 서로 같은 모양 두 가지를 비교하는거야? 무슨 NaN뜻입니까?



답변

NaN은 “숫자가 아님”을 의미합니다.

JLS (Java Language Specification) Third Edition의 내용 :

오버플로 된 연산은 부호있는 무한대를 생성하고, 언더 플로 된 연산은 비정규 화 된 값 또는 부호있는 0을 생성하며, 수학적으로 명확한 결과가없는 연산은 NaN을 생성합니다. 피연산자로 NaN을 사용하는 모든 숫자 연산은 결과적으로 NaN을 생성합니다. 이미 설명했듯이 NaN은 순서가 없으므로 NaN이 포함 된 경우를 포함하여 하나 또는 두 개의 NaN 반환 false과 NaN 반환 과 !=관련된 모든 비교가 true포함 x!=x됩니다 x.


답변

NaN은 정의상 NaN을 포함한 숫자와 같지 않습니다. 이것은 IEEE 754 표준의 일부이며 CPU / FPU에 의해 구현됩니다. JVM이 지원할 논리를 추가해야하는 것은 아닙니다.

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

NaN과의 비교는 자체와 비교할 때도 항상 정렬되지 않은 결과를 반환합니다. … 항등 및 부등식 술어는 신호가 없으므로 x = x는 false를 반환하여 x가 조용한 NaN인지 테스트하는 데 사용할 수 있습니다.

Java는 모든 NaN을 조용한 NaN으로 취급합니다.


답변

왜 그 논리

NaN의미 Not a Number합니다. 숫자가 아닌 것은 무엇입니까? 아무것도. 한쪽과 다른쪽에 무엇이든 가질 수 있으므로 둘 다 동일하다는 보장은 없습니다. NaN로 계산 Double.longBitsToDouble(0x7ff8000000000000L)되고 다음 문서에서 볼 수 있습니다 longBitsToDouble:

인수의 범위에있는 값이면 0x7ff0000000000001L통해
0x7fffffffffffffffL또는 범위의 0xfff0000000000001L관통은
0xffffffffffffffffL, 그 결과는이다 NaN.

또한 NaN논리적으로 API 내부에서 처리됩니다.


선적 서류 비치

/**
 * A constant holding a Not-a-Number (NaN) value of type
 * {@code double}. It is equivalent to the value returned by
 * {@code Double.longBitsToDouble(0x7ff8000000000000L)}.
 */
public static final double NaN = 0.0d / 0.0;

그런데, NaN 되는 코드 샘플로 테스트 :

/**
 * Returns {@code true} if the specified number is a
 * Not-a-Number (NaN) value, {@code false} otherwise.
 *
 * @param   v   the value to be tested.
 * @return  {@code true} if the value of the argument is NaN;
 *          {@code false} otherwise.
 */
static public boolean isNaN(double v) {
    return (v != v);
}

해결책

당신이 할 수있는 일은 use compare/ compareTo:

Double.NaN이 방법으로이 값은 자체와 같고 다른 모든 double값 (포함
Double.POSITIVE_INFINITY) 보다 큽니다 .

Double.compare(Double.NaN, Double.NaN);
Double.NaN.compareTo(Double.NaN);

또는 equals:

경우 thisargument두 대표 Double.NaN, 다음 equals메소드가 리턴은 true, 비록
Double.NaN==Double.NaN값이 있습니다 false.

Double.NaN.equals(Double.NaN);


답변

질문에 대한 직접적인 답변이 아닐 수도 있습니다. 그러나 무언가가 같은지 확인하려면 Double.NaN다음을 사용해야합니다.

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

이것은 돌아올 것이다 true


답변

Double.NaN에 대한 javadoc은 다음과 같이 말합니다.

유형의 NaN (Not-a-Number) 값을 보유하는 상수 double입니다. 에서 반환 한 값과 같습니다 Double.longBitsToDouble(0x7ff8000000000000L).

흥미롭게도 소스 Double는 다음과 NaN같이 정의됩니다 .

public static final double NaN = 0.0d / 0.0;

설명하는 특수 동작은 JVM에 연결되어 있습니다.


답변

배정 밀도 숫자의 부동 소수점 산술에 대한 IEEE 표준에 따라

IEEE 배정 밀도 부동 소수점 표준 표현에는 64 비트 워드가 필요합니다. 64 비트 워드는 0에서 63까지의 숫자로 표시 될 수 있습니다 (왼쪽에서 오른쪽으로).

여기에 이미지 설명을 입력하십시오
어디,

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

만약 E=2047(모든 E입니다 1) 및 F다음 제로가된다 V=NaN( “숫자가 아님”)

즉,

모든 E비트가 1이고 0이 아닌 비트가 있으면 F숫자는 NaN입니다.

따라서 다른 모든 숫자는 다음과 같습니다. NaN ,

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

특히 테스트 할 수 없습니다

if (x == Double.NaN) 

Double.NaN모든 “숫자가 아님”값이 고유 한 것으로 간주되므로 특정 결과가과 같은지 여부를 확인합니다 . 그러나 다음 Double.isNaN방법을 사용할 수 있습니다 .

if (Double.isNaN(x)) // check whether x is "not a number"


답변

NaN은 “숫자가 아님”을 나타내는 특수 값입니다. 와 같은 특정 잘못된 산술 연산의 결과이며 sqrt(-1)(때로는 성가신) 속성이 NaN != NaN있습니다.