방금 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
:
경우
this
와argument
두 대표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
있습니다.
