NaN
덤프버전 :
||
Not a Number, NaN[1]
NaN은 잘못된 입력으로 인해 계산을 할 수 없음을 나타내는 기호이다. 이를테면 음수의 제곱근을 구하려고 한다거나, 수만 나타낼 수 있는 변수에 텍스트를 넣었을때 일어나며, 일부 언어에서는 0으로 나눈 몫을 구하려고 할 때 예외를 던지는 대신 NaN을 반환하기도 한다. 이는 실수만을 저장할 수 있는 기본 부동소수점 저장체계에는 저장할 수 없는 허수나 실존하지 않는 수를 저장할 수 없기 때문에 오류 대신 반환하는 리턴값이다.
JavaScript에서는 숫자와 문자를 연산하거나, 숫자가 아닌 수를 파싱하려 할 때 주로 리턴되며, Java에서는 부정형[2] 을 계산하려 하거나 Math 함수로 연산시 잘못된 값(제곱근 함수에 음수 입력 등)이 들어가면 주로 리턴된다. (자바스크립트에서 0이 아닌 숫자를 0으로 나누면
그리고 무한이라는 뜻은 아니다. 물론 무한으로 취급되는 경우가 많긴 하다. 하지만 어떤 경우에는 0보다 못한 음의 무한이 될 수도 있다. 만약 돈이 NaN이면 물건을 무한히 살 수 있지만 최소 0보다 커야 하는 값이 NaN이면 오히려 0만도 못하다.
어떤 사람은 NaN 대신 예외를 던지는게 더 나을 것이라고 생각할 수도 있다. 하지만 꼭 그런것만은 아닌게 사용자가 입력을 한 값을 프로그램의 알고리즘에 대입을 했을 때 개발자가 예상치 못한 오류는 항상 생길 수 있으며 그럴 때마다 프로그램이 오류를 뿜으려 종료되는 것은 좋지 못하기 때문에 일단 프로그램은 잘 돌아가도록 NaN을 반환하는게 이득일 때도 있다.
자바스크립트에서, NaN은 참 NaN인지 알아내기 어려운 값이다.
하지만 자바스크립트에선 여전히 마땅히 예외가 발생해야 할 이상한 연산에서도 NaN이 나오고 마는 경우가 있어 디버깅이 어려워지는 등의 문제가 있다.
수학적으로 보면 이 개념이 이상하게 보일 수 있다. [math(\sqrt{-0} = {\sf NaN})]이라면 말이 되는가?[4]
1. 개요[편집]
Not a Number, NaN[1]
NaN은 잘못된 입력으로 인해 계산을 할 수 없음을 나타내는 기호이다. 이를테면 음수의 제곱근을 구하려고 한다거나, 수만 나타낼 수 있는 변수에 텍스트를 넣었을때 일어나며, 일부 언어에서는 0으로 나눈 몫을 구하려고 할 때 예외를 던지는 대신 NaN을 반환하기도 한다. 이는 실수만을 저장할 수 있는 기본 부동소수점 저장체계에는 저장할 수 없는 허수나 실존하지 않는 수를 저장할 수 없기 때문에 오류 대신 반환하는 리턴값이다.
JavaScript에서는 숫자와 문자를 연산하거나, 숫자가 아닌 수를 파싱하려 할 때 주로 리턴되며, Java에서는 부정형[2] 을 계산하려 하거나 Math 함수로 연산시 잘못된 값(제곱근 함수에 음수 입력 등)이 들어가면 주로 리턴된다. (자바스크립트에서 0이 아닌 숫자를 0으로 나누면
Infinity
가 나오며, 자바에서도 double이나 float에서 0으로 나누면 동일한 결과가 나온다.[3] )그리고 무한이라는 뜻은 아니다. 물론 무한으로 취급되는 경우가 많긴 하다. 하지만 어떤 경우에는 0보다 못한 음의 무한이 될 수도 있다. 만약 돈이 NaN이면 물건을 무한히 살 수 있지만 최소 0보다 커야 하는 값이 NaN이면 오히려 0만도 못하다.
2. 필요성[편집]
어떤 사람은 NaN 대신 예외를 던지는게 더 나을 것이라고 생각할 수도 있다. 하지만 꼭 그런것만은 아닌게 사용자가 입력을 한 값을 프로그램의 알고리즘에 대입을 했을 때 개발자가 예상치 못한 오류는 항상 생길 수 있으며 그럴 때마다 프로그램이 오류를 뿜으려 종료되는 것은 좋지 못하기 때문에 일단 프로그램은 잘 돌아가도록 NaN을 반환하는게 이득일 때도 있다.
3. 문제점[편집]
자바스크립트에서, NaN은 참 NaN인지 알아내기 어려운 값이다.
x == NaN
같은 비교 연산으로 알아낼 수 있나 싶겠지만, NaN == NaN
은 false
가 나오는 것을 확인할 수 있고, 일치 연산자 ===를 사용해도 NaN === NaN
은 false가 나온다[* 역설적으로, 이걸 이용해 NaN을 구분하는 함수를 만들 수 있다! const isNaN2 = _ => _ !== _
]. 전역 함수로 isNaN()이 있지만, 이 함수는 정확히 말하면 '어떤 값이 숫자로 변환될 수 있는지'를 알려주는 함수인 데에다, null을 false
로 판단하는 등의 문제가 있었다. (이 문제는 ES6에서 Number.isNan()
함수가 나오며 해결되었다.)하지만 자바스크립트에선 여전히 마땅히 예외가 발생해야 할 이상한 연산에서도 NaN이 나오고 마는 경우가 있어 디버깅이 어려워지는 등의 문제가 있다.
수학적으로 보면 이 개념이 이상하게 보일 수 있다. [math(\sqrt{-0} = {\sf NaN})]이라면 말이 되는가?[4]
4. 각종 언어에서의 NaN 예시[편집]
Console.WriteLine(Math.Sqrt(-3));
Console.WriteLine(double.NaN);
33 - "a" // NaN
parseInt("abc") // NaN
0 / 0 // NaN
}}}--'b' + 'a' + + 'n' + 'a' // [[바나나|baNaNa]]--
System.out.println(0.0D / 0.0D);
System.out.println(Double.NaN);
import numpy
print(numpy.NaN)
let x = 1.21
let y = x + Double.nan
print(y == Double.nan)
print(y.isNaN)
}}}상기 코드에서 "print(y == Double.nan)" 코드는 false를 내뱉지만, print(y.isNaN) 코드는 true를 출력한다. 일반적인 상황에서 Swift는 NaN 에러를 출력하지 않지만, {{{#!syntax swift .isNaN}}}을 변수명 뒤에 붙이는 것으로 해당 변수가 숫자인지, 숫자가 아닌지 Bool값을 출력할 수 있다. 숫자가 아니면 true, 숫자라면 false. 이렇게 복잡한 이유는, Swift는 NaN을 Float값의 하나로 처리하기 때문. [[https://developer.apple.com/documentation/swift/float/nan|코드 출처]]
이와 같은 논리로, 하기 코드도 NaN으로 인식된다.
let number: Double = 0.0 / 0.0
print(number.isNaN)
}}}다만, 일부 언어와 달리 단순 print(0/0)을 돌려도 NaN이 출력되지는 않고, print(0.0/0.0)을 실행해야 nan이 출력된다. 이 역시 상술했듯 Swift에서 NaN을 Int가 아닌 Float(혹은 Double)의 일환으로 처리하기 때문. 단순히 Int값으로 0/0을 출력하려고 하면 "error: division by zero"로 컴파일 에러가 발생한다.
이 문서의 내용 중 전체 또는 일부는 2023-10-31 13:25:51에 나무위키 NaN 문서에서 가져왔습니다.
[1] N이 2개 있지만 서로 다른 뜻이다.[2] 0 / 0, Infinity * 0, Infinity - Infinity, Infinity / Infinity 등. 물론 2의 1024제곱 이상의 모든 수는 무한으로 취급한다. 반대로 5e-324보다 작아지면 0으로 취급한다. 그리고 현재 값의 10경 분의 1도 안되는 값은 더하거나 빼는 건 아예 안 한 것과 같은 것으로 취급한다.[3] 단, int 등 정수값의 경우 java.lang.ArithmeticException: / by zero 예외가 발생한다.[4] 수학적으로는 그냥 [math(0)]이다.[5] 다음 두 줄의 코드는 모두 NaN을 출력한다.