NaN
다시 보기기본적으로 NaN
은 "숫자가 아님"을 나타내는 특별한 부동소수점 값입니다. 예를 들어 0을 0으로 나누거나, 음수의 제곱근을 구하는 등의 수학적으로 정의되지 않는 연산의 결과로 주로 발생합니다.
NaN
의 가장 큰 특징은 자기 자신을 포함한 그 어떤 값과도 같지 않다는 것입니다.
NaN == NaN
은 false
입니다.NaN
은 다른 어떤 숫자보다 크거나 작다고 말할 수 없습니다. 즉,
NaN > 1.0도
false이고,
NaN < 1.0도
false`입니다.이는 NaN
이 특정 숫자를 나타내는 것이 아니라, "정의되지 않은 또는 표현할 수 없는 숫자"라는 상태를 의미하기 때문입니다. 따라서 두 개의 NaN
값이 있다고 해서 그 둘이 같은 "정의되지 않은 상태"라고 단정할 수 없습니다.
NaN
하지만 컬렉션, 특히 정렬된 컬렉션(예: TreeSet
또는 sortedSetOf
를 통해 생성된 컬렉션)에서 NaN
을 다룰 때는 동작 방식이 조금 다릅니다. 이는 IEEE 754 표준 부동소수점 산술 규칙과 JVM의 특정 구현 방식 때문입니다.
val set = sortedSetOf(Double.NaN, Double.NaN,Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY,0.0)
println(set) // [-Infinity, 0.0, Infinity, NaN]
위 코드의 sortedSetOf(Double.NaN, Double.NaN, Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY, 0.0)
를 실행했을 때, 결과는 [-Infinity, 0.0, Infinity, NaN]
입니다.
여기서 주목할 점은 다음과 같습니다.
NaN
은 자기 자신과 같다 (컬렉션 내에서 유일성 보장):
NaN == NaN
이 false
이지만, Set
과 같은 컬렉션은 요소의 유일성을 보장해야 합니다.sortedSetOf
(내부적으로 TreeSet
사용 가능)에 NaN
을 여러 번 추가하더라도, 컬렉션 내에는 하나의 NaN
만 저장됩니다. 이는 NaN
을 컬렉션에 넣을 때, 이미 NaN
이 존재하는지를 확인하는 과정에서 NaN
을 "같은" 것으로 간주하기 때문입니다. (정확히는 equals()
메서드와 compareTo()
메서드의 동작 방식에 따릅니다. Double.NaN.equals(Double.NaN)
은 true
를 반환합니다.)NaN
의 정렬 순서 (자연적 순서):sortedSetOf
는 요소를 자연적인 순서(natural ordering
)에 따라 정렬합니다.
Double
타입의 자연적 순서에서 NaN
은 가장 큰 값으로 취급됩니다. 심지어 Double.POSITIVE_INFINITY
(양의 무한대)보다도 더 큰 값으로 간주되어 정렬 순서상 가장 마지막에 위치하게 됩니다.