IEEE754 NaN 값에 대해 false를 반환하는 모든 비교의 이론적 근거는 무엇입니까?


267

NaN 값 비교가 다른 모든 값과 다르게 동작하는 이유는 무엇입니까? 즉, 연산자 ==, <=,> =, <,>와의 모든 비교에서 하나 또는 두 값이 모두 NaN이면 다른 모든 값의 동작과 반대로 false를 반환합니다.

나는 이것이 어떤 식 으로든 수치 계산을 단순화한다고 생각하지만 Kahan 의 IEEE 754 상태 에 관한 강의 노트 조차도 다른 설계 결정에 대해 자세히 설명 하지 않는 명백한 이유를 찾을 수 없었습니다 .

이탈 한 동작은 간단한 데이터 처리를 수행 할 때 문제를 일으 킵니다. 예를 들어 C 프로그램에서 일부 실제 필드를 사용하여 레코드 목록을 정렬 할 때 NaN을 최대 요소로 처리하기 위해 추가 코드를 작성해야합니다. 그렇지 않으면 정렬 알고리즘이 혼란 스러울 수 있습니다.

편집 : 지금까지의 대답은 NaN을 비교하는 것이 의미가 없다고 주장합니다.

동의하지만 그렇다고해서 정답이 거짓임을 의미하는 것은 아니며 부울이 아님 (NaB) 일 것입니다.

따라서 비교를 위해 true 또는 false를 반환하는 선택은 임의의 견해이며 일반적인 데이터 처리의 경우 일반적인 법칙 (= = 반사율, <, ==,>의 트리 코미 네이션)을 준수하면 데이터 구조가 가장 유리합니다. 이 법에 의존하는 것은 혼란스러워집니다.

그래서 나는 철학적 추론뿐만 아니라 이러한 법을 어기면 어떤 구체적인 이점을 요구하고 있습니다.

편집 2 : NaN을 최대로 만드는 것이 나쁜 생각이되는 이유를 이해한다고 생각합니다. 상한값 계산을 망칠 것입니다.

NaN! = NaN은 다음과 같은 루프에서 수렴을 감지하지 않기 위해 바람직 할 수 있습니다.

while (x != oldX) {
    oldX = x;
    x = better_approximation(x);
}

그러나 절대 차이를 작은 한계와 비교하여 더 잘 작성해야합니다. 따라서 IMHO는 NaN에서 반사성을 깨뜨리기위한 비교적 약한 주장입니다.


2
NaN이 계산에 들어간 후에는 계산이 종료되지 않으므로 수렴 테스트는 무한 루프가됩니다. 일반적으로 NaN을 반환하여 호출 루틴에 수렴하지 못한 것을보고하는 것이 좋습니다. 따라서 루프 구조는 일반적으로 while (fabs(x - oldX) > threshold)수렴이 발생하거나 NaN이 계산에 들어가면 루프를 종료하는 것과 같이 됩니다. NaN의 탐지 및 적절한 해결책은 루프 외부에서 발생합니다.
Stephen Canon

1
NaN이 순서의 최소 요소라면 while 루프는 여전히 작동합니다.
starblue

2
생각을위한 음식 : grouper.ieee.org/groups/1788/email/pdfmPSi1DgZZf.pdf 10 페이지
starblue

답변:


535

저는 IEEE-754위원회의 일원이었습니다. 일을 좀 더 명확하게하려고 노력할 것입니다.

먼저 부동 소수점 숫자는 실수가 아니며 부동 소수점 산술은 실제 산술의 공리를 만족시키지 않습니다. Trichotomy는 수레뿐만 아니라 가장 중요하지 않은 실제 산술의 유일한 속성은 아닙니다. 예를 들면 다음과 같습니다.

  • 덧셈은 연관성이 없습니다.
  • 분배 법은 유지하지 않습니다.
  • 역수가없는 부동 소수점 숫자가 있습니다.

계속할 수있었습니다. 우리가 알고 사랑하는 실제 산술의 모든 속성 을 만족시키는 고정 크기 산술 유형을 지정할 수 없습니다 . 754위원회는 그들 중 일부를 구부리거나 파기로 결정해야합니다. 이것은 매우 간단한 원칙에 의해 안내됩니다.

  1. 우리가 할 수있을 때, 우리는 실제 산술 행동과 일치합니다.
  2. 우리가 할 수 없을 때, 우리는 위반을 예측 가능하고 진단하기 쉬운 것으로 만들려고 노력합니다.

"정답이 거짓이라는 의미는 아닙니다"라는 귀하의 의견과 관련하여 이것은 잘못된 것입니다. 술어 가보다 작은 (y < x)지 묻습니다 . 경우 NaN이입니다, 다음은 하지 부동 소수점 값보다 적은 답은 반드시 거짓 있도록.yxyx

나는 trichotomy가 부동 소수점 값을 유지하지 않는다고 언급했습니다. 그러나 유사한 속성이 있습니다. 754-2008 표준의 조항 5.11, 단락 2 :

4 가지 상호 배타적 인 관계가 가능합니다. 마지막 경우는 하나 이상의 피연산자가 NaN 일 때 발생합니다. 모든 NaN은 비 순차적 자체를 포함하여 모든 것을 비 교해야한다.

NaN을 처리하기 위해 추가 코드를 작성하는 한 NaN이 제대로 빠져 나가는 방식으로 코드를 구성하는 것이 가능하지만 항상 쉬운 것은 아니지만 항상 그런 것은 아닙니다. 그렇지 않은 경우 일부 추가 코드가 필요할 수 있지만 대수 종결이 부동 소수점 산술에 가져온 편의성을 지불하는 것은 작은 가격입니다.


부록 : 많은 의견 제시 자들은 NaN! = NaN을 채택하는 것이 친숙한 공리를 보존하지 않는 근거로 평등과 삼분 절의 반사성을 유지하는 것이 더 유용 할 것이라고 주장했다. 나는이 견해에 대해 동정심을 가지고 있다고 고백했다. 그래서 나는이 답변을 다시 방문하고 좀 더 많은 맥락을 제공 할 것이라고 생각했다.

Kahan과의 대화에서 NaN! = NaN은 두 가지 실용적인 고려 사항에서 비롯된 것입니다.

  • x == y동등해야한다 x - y == 0이것은 X의 위반, 그러나, 참고 -이 표준이 개발되었을 때 가장 중요했다 비해 더 많은 공간 효율의 하드웨어 구현한다 가능하면 (실제 연산의 정리되고 넘어 = y = 무한대이므로, 그 자체로는 큰 이유가 아닙니다 (x - y == 0) or (x and y are both NaN).

  • 더 중요한 isnan( )것은 NaN이 8087 산술로 공식화 될 당시에는 술어 가 없었다는 것입니다. isnan( )수년이 걸릴 수 있는 프로그래밍 언어에 의존하지 않는 NaN 값을 감지하는 편리하고 효율적인 수단을 프로그래머에게 제공 해야했습니다. 이 주제에 대한 Kahan의 글을 인용하겠습니다.

NaN을 제거 할 수있는 방법이 없었다면 CRAY에서 무기한만큼 쓸모가 없을 것입니다. 하나가 발생하자마자 무기한 결론을 내릴 때까지 무한정 계속되는 것이 아니라 계산을 중단하는 것이 가장 좋습니다. 그렇기 때문에 NaN에 대한 일부 작업은 NaN 이외의 결과를 제공해야합니다. 어떤 작업? … 예외는 C 술어 "x == x"및 "x! = x"이며, 이는 모든 무한 또는 유한 수 x에 대해 각각 1과 0이지만 x가 숫자가 아님 (NaN)이면 역전됩니다. 이것들은 NaN에 대한 단어와 술어 IsNaN (x)가없는 언어의 NaN과 숫자 사이의 단순한 예외없는 구별을 제공합니다.

이것은 "부울이 아님"과 같은 것을 반환하지 않는 논리이기도합니다. 어쩌면이 실용주의가 잘못 배치되어 표준이 필요 isnan( )했을 것입니다. 그러나 NaN은 몇 년 동안 효율적이고 편리하게 사용하기가 거의 불가능 해졌지만 세계는 프로그래밍 언어 채택을 기다렸습니다. 나는 합리적인 트레이드 오프가 될 것이라고 확신하지 않습니다.

둔감하게 : NaN == NaN의 결과는 지금 바뀌지 않을 것입니다. 인터넷에서 불평하는 것보다 함께 사는 법을 배우는 것이 좋습니다. 컨테이너에 적합한 주문 관계 존재 해야한다고 주장하려면 선호하는 프로그래밍 언어 totalOrder가 IEEE-754 (2008)에 표준화 된 술어를 구현하도록 권장합니다 . 그것이 현재 상황에 동기를 부여한 Kahan의 우려의 타당성을 아직 밝히지 않았다는 사실.


16
나는 당신의 포인트 1과 2를 읽었습니다. 그리고 나서 실제 산술에서 (처음에 NaN을 허용하도록 확장 됨) NaN은 그 자체와 같습니다. 단순히 수학에서 예외없이 모든 엔티티가 자신과 동일하기 때문입니다. 이제 혼란스러워합니다. 왜 IEEE가 "실제 산술 동작과 일치하지"않았습니까? NaN == NaN이 되었습니까? 내가 무엇을 놓치고 있습니까?
최대

12
합의 NaN의 비 반사성은 평등 기반의 격리 의미론으로 파이썬과 같은 언어에 대한 고통을 종식시키지 못했습니다. 당신은 정말 당신이 그 위에 빌드 컨테이너에 노력하고 때 동치 관계로 실패 평등을 원하지 않는다. 그리고 두 개의 서로 다른 평등 개념을 갖는 것은 배우기 쉬운 언어의 경우 친숙한 선택이 아닙니다. 결과는 (파이썬의 경우) IEEE 754에 대한 존중과 그다지 깨지지 않은 격리 의미론 사이의 불쾌한 취약성입니다. 다행히 NaN을 컨테이너에 넣는 일은 드 rare니다.
Mark Dickinson

5
좋은 관찰은 여기 : bertrandmeyer.com/2010/02/06/…
Mark Dickinson

6
@StephenCanon : (0/0) == (+ INF) + (-INF)는 어떤 방법으로 더 무의미 1f/3f == 10000001f/30000002f합니까? 부동 소수점 값이 동등성 클래스로 간주되는 경우 a=b" 무한 정밀도로 수행 된 계산 a및 계산 b결과 동일한 결과가 생성됨"을 의미하는 것이 아니라 "알려진 내용 a과 일치하는 것으로 알려진 내용" b". "Nan! = NaN"을 사용하면 다른 것보다 간단하게 만드는 코드의 예를 알고 있다면 궁금합니다.
supercat

5
이론적으로 NaN == NaN이고 isNaN이없는 경우으로 NaN을 테스트 할 수 !(x < 0 || x == 0 || x > 0)있지만 x != x.
user2357112는 Monica

50

NaN은 정의되지 않은 상태 / 번호로 생각할 수 있습니다. 0/0의 개념은 undefined 또는 sqrt (-3) (부동 소수점이있는 실수 시스템에서)라는 개념과 유사합니다.

NaN은이 정의되지 않은 상태에 대한 일종의 자리 표시 자로 사용됩니다. 수학적으로 말하면 undefined는 undefined와 다릅니다. 정의되지 않은 값이 다른 정의되지 않은 값보다 크거나 작다고 말할 수는 없습니다. 따라서 모든 비교는 false를 반환합니다.

sqrt (-3)와 sqrt (-2)를 비교하는 경우에도이 동작이 유리합니다. 둘 다 NaN을 반환하지만 동일한 값을 반환하더라도 동등하지 않습니다. 그러므로 NaN을 다룰 때 평등을 갖는 것은 항상 잘못된 행동입니다.


5
sqrt (1.00000000000000022) == sqrt (1.0)의 결과는 무엇입니까? (1E308 + 1E308-1E308-1E308-1E308) == (1E308 + 1E308)는 어떻습니까? 또한 6 개의 비교 중 5 개만 거짓을 반환합니다. !=연산자는 true를 반환합니다. 데 NaN==NaNNaN!=NaN모두 반환 거짓은 X를 비교 코드를 허용 할 y는 두 피연산자 중 하나를 선택하여 NaN이를 때 발생해야하는 선택 ==하거나 !=.
supercat

38

또 다른 비유를 던져라. 상자 두 개를 건네고 사과 중 어느 것도 사과가 들어 있지 않다고 말하면 상자에 같은 것이 들어 있다고 말할 수 있습니까?

NaN에는 무엇인가에 대한 정보가 없습니다. 따라서 이러한 요소는 절대 동일하다고 말할 수 없습니다.


6
모든 빈 세트는 정의상 동일합니다.
MSalters

28
제공된 상자가 비어있는 것으로 알려져 있지 않습니다.
John Smith

7
상자에 같은 것이 포함되어 있지 않다고 말씀해 주시겠습니까? 의 이론적 근거를 이해할 수 있습니다 (NaN==Nan)==false. 내가 이해하지 못하는 것은의 이론적 근거입니다 (Nan!=Nan)==true.
supercat

3
x! = y가! (x == y)로 정의 되었기 때문에 NaN! = NaN이 참이라고 가정합니다. 물론, IEEE 사양이 그렇게 정의하고 있는지 모르겠습니다.
Kef Schecter

6
그러나이 비유에서 상자를 줬다면 사과가 들어 있지 않다고 말한 다음 그 자체와 같은지 물어 보면 아니오라고 말할 것입니까? 그것이 IEEE에 따라 말해야 할 것이기 때문입니다.
세미콜론

12

NaN 에 대한 Wikipedia 기사에서 다음과 같은 관행으로 인해 NaN이 발생할 수 있습니다.

  • NaN을 하나 이상의 피연산자로 사용하는 모든 수학 연산>
  • 0/0, ∞ / ∞, ∞ / -∞, -∞ / ∞ 및 -∞ / -∞ 나누기
  • 곱셈 0 × ∞ 및 0 × -∞
  • 더하기 ∞ + (-∞), (-∞) + ∞ 및 동등한 빼기.
  • 음수의 제곱근을 취하거나, 음수의 로그를 취하거나, 90 도의 홀수 배수 (또는 π / 2 라디안)의 탄젠트를 취하거나, 역 사인을 취하는 등 함수를 도메인 외부의 인수에 적용 또는 -1보다 작거나 +1보다 큰 수의 코사인.

NaN을 생성 한 이러한 작업을 알 수있는 방법이 없으므로 의미가있는 작업을 비교할 방법이 없습니다.


3
또한 어떤 작업을 알더라도 도움이되지 않습니다. 어떤 시점에서 0/0으로 이동하는 많은 수의 수식을 구성 할 수 있으며, 그 지점에서 (연속성을 가정하면) 잘 정의되고 다른 값을 갖습니다.
David Thornley

4

디자인의 이론적 근거를 모르지만 다음은 IEEE 754-1985 표준에서 발췌 한 것입니다.

"피연산자의 형식이 다른 경우에도 지원되는 모든 형식의 부동 소수점 숫자를 비교할 수 있습니다. 비교는 정확하고 오버플로 또는 언더 플로가 아닙니다. 상호 배타적 인 관계는 가능합니다. 마지막 사건은 적어도 하나의 피연산자가 NaN 인 경우에 발생합니다. 모든 NaN은 순서가없는 것을 자기 자신을 포함한 모든 것과 비교해야합니다. "


2

NaN을 허용하는 대부분의 프로그래밍 환경은 3 값 논리도 허용하지 않기 때문에 독특하게 보입니다. 3 값 논리를 믹스에 넣으면 일관성이 유지됩니다.

  • (2.7 == 2.7) = 그렇습니다
  • (2.7 == 2.6) = 거짓
  • (2.7 == NaN) = 알 수 없음
  • (NaN == NaN) = 알 수 없음

.NET조차도 bool? operator==(double v1, double v2) 연산자를 여전히 어리석은 (NaN == NaN) = false결과에 갇혀 있습니다.


1

NaN (Not A Number)은 정확히 다음을 의미한다고 추측합니다. 이것은 숫자가 아니므로 비교하는 것이 실제로 의미가 없습니다.

null피연산자가 있는 SQL의 산술과 ​​비슷 null합니다. 결과는 모두입니다 .

부동 소수점 숫자의 비교는 숫자 값을 비교합니다. 따라서 숫자가 아닌 값에는 사용할 수 없습니다. 따라서 NaN은 숫자로 비교할 수 없습니다.


3
"이 숫자는 아니므로 비교하는 것이 의미가 없습니다." 문자열은 숫자가 아니지만 비교하는 것이 좋습니다.
제이슨

2
예, 문자열과 문자열을 비교하는 것이 좋습니다. 그러나 사과와 문자열을 비교하는 것은 의미가 없습니다. 사과와 배는 숫자가 아니기 때문에 비교하는 것이 합리적입니까? 어느 것이 더 큽니까?
Daren Thomas

@DarenThomas : SQL에서 "IF NULL = NULL THEN FOO;" "IF Null <> Null THEN CALL FOO;" [또는 구문이 무엇이든]이 실행 FOO됩니다. NaN이 동등하기 if (NaN != NaN) foo();위해서는 실행하지 않아야 foo하지만 실행 됩니다.
supercat

1

지나치게 단순화 된 답변은 NaN에 숫자 값이 없으므로 다른 것과 비교할 값이 없다는 것입니다.

NaN을 + INF처럼 작동 시키려면 NaN을 테스트하고 + INF로 교체하는 것을 고려할 수 있습니다.


0

NaN과 실수를 비교하는 것은 순서가 맞지 않아야한다는 데 동의하지만 NaN과 자체를 비교하는 데는 이유가 있다고 생각합니다. 예를 들어 신호 NaN과 조용한 NaN의 차이점을 어떻게 발견합니까? 신호를 부울 값 세트 (예 : 비트 벡터)로 생각하면 비트 벡터가 동일한 지 또는 다른지를 묻고 그에 따라 세트를 정렬 할 수 있습니다. 예를 들어, 최대 바이어스 지수를 디코딩 할 때 이진수 형식의 최상위 비트와 최상위 비트를 정렬하기 위해 유효 비트가 시프트 된 경우 음수 값은 조용한 NaN이되고 양수 값은 신호 NaN이어야합니다. 물론 제로는 무한대로 예약되어 있으며 비교는 순서가 없습니다. MSB 정렬을 통해 서로 다른 이진 형식의 신호를 직접 비교할 수 있습니다. 따라서 동일한 신호 세트를 가진 두 개의 NaN은 동일하며 동등성을 의미합니다.


-1

나를 위해 가장 쉬운 방법은 다음과 같습니다.

나는 무언가가 있고 그것이 사과가 아니라면 오렌지입니까?

NaN은 값이 없기 때문에 다른 것 (심지어 그 자체)과 비교할 수 없습니다. 또한 숫자를 제외한 모든 값이 될 수 있습니다.

나는 무언가가 있고 그것이 숫자와 같지 않으면 문자열입니까?


"숫자를 제외한 모든 값이 될 수 있습니다"는 무슨 뜻입니까?
pushkin

-2

수학은 숫자가 "존재하는"필드이기 때문입니다. 컴퓨팅에서는 해당 숫자 를 초기화 하고 필요에 따라 상태를 유지 해야합니다. 그 옛날에는 메모리 초기화가 결코 신뢰할 수 없었던 방식으로 작동했습니다. 당신은 결코 "오, 그것은 0xCD로 초기화 될 것이고, 나의 algo는 깨지지 않을 것입니다" 라고 생각할 수 없었습니다 .

따라서 알고리즘에 빨려 들어 가지 않도록 충분히 끈적 거리지 않는 적절한 비 혼합 용매 가 필요합니다 . 숫자와 관련된 좋은 알고리즘은 대부분 관계와 함께 작동하며 if () 관계는 생략됩니다.

이것은 컴퓨터 메모리에서 무작위 지옥을 프로그래밍하는 대신 생성시 새로운 변수에 넣을 수있는 그리스 일뿐입니다. 그리고 알고리즘이 무엇이든간에 깨지지 않습니다.

다음으로 알고리즘이 NaN을 생성하고 있다는 것을 갑자기 발견하면 한 번에 하나씩 모든 분기를 살펴보면서이를 정리할 수 있습니다. 다시, "항상 거짓"규칙이 이것에 많은 도움이됩니다.


-4

매우 짧은 답변 :

다음과 같은 이유로 : nan / nan = 1 잡고 있으면 안됩니다. 그렇지 않으면 inf/inf1이됩니다.

(따라서 nan동일 할 수 없다 nan.로서는을 >하거나 <하는 경우, nan아르키메데스 속성을 만족시키는 집합의 임의의 순서 관계를 존중 것, 우리는 다시했을 nan / nan = 1한도에서).


2
아니요, 말이되지 않습니다. 우리는이 inf = infinf / inf = nan그렇게 nan = nan막을 수 없습니다 nan / nan = nan중 하나.
starblue

@starblue 당신은 nan / nan = 1? 어쨌든 ... inf와 nan이 다른 숫자와 똑같다면 당신의 추론은 의미가 있습니다. 그렇지 않습니다. 그 이유 는 수학에서 불확실한 형태 inf/inf여야 하는 이유 는 단순한 대수적 조작보다 미묘합니다 (De L' Hospital 정리 참조). nan1
SeF
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.