Programming

NaN이 NaN과 다른 이유는 무엇입니까?

procodes 2020. 7. 26. 13:08
반응형

NaN이 NaN과 다른 이유는 무엇입니까? [복제]


관련 IEEE 표준은 숫자 상수 NaN (숫자가 아님)을 정의하고 NaN이 자신과 같지 않은 것으로 비교하도록 규정합니다. 왜 그런 겁니까?

내가 익숙한 모든 언어가이 규칙을 구현합니다. 그러나 NaN이 컨테이너에 저장 될 때 NaN이 정렬되는 데이터에있을 때 예기치 않은 동작과 같은 중요한 문제가 종종 발생합니다. 말할 것도없이 대다수의 프로그래머는 객체가 자신과 동일 할 것으로 예상합니다 ( 그들이 NaN에 대해 배우기 전에), 놀랍게도 버그와 혼란을 더합니다.

IEEE 표준은 잘 알려져 있으므로 NaN을 자체와 비교하는 것이 좋지 않은 이유가 있다고 확신합니다. 나는 그것이 무엇인지 알 수 없습니다.


허용 된 답변은 의문의 여지없이 100 % 입니다. 반쯤 잘못되거나 약간 잘못되지도 않습니다. 이 문제가 검색에서이 질문이 나타날 때 오랫동안 혼란스러워하고 프로그래머를 오도하게 될 것 같습니다.

NaN은 모든 계산을 통해 전파하여 바이러스처럼 감염 시키도록 설계되었으므로 NaN에 대한 심도 있고 복잡한 계산의 어딘가에있는 경우에는 겉보기에 합리적인 대답이 나오지 않습니다. 그렇지 않으면 동일성에 의해 NaN / NaN은 (NaN / NaN) == 1, (NaN * 1) == NaN 등과 같은 다른 모든 결과와 함께 1과 같아야합니다. 계산이 어딘가에 잘못되었다고 생각되면 (반올림 분모 제로, NaN 생성) 등의 이유에 대한 명확한 지표없이 계산 결과가 크게 잘못 될 수 있습니다.

수학적 함수의 값을 조사 할 때 NaN이 계산에 실제로 필요한 이유도 있습니다. 링크 된 문서에 주어진 예제 중 하나는 함수 f ()의 zeros ()를 찾는 것입니다. 추측 값으로 함수를 프로빙하는 과정에서 함수 f ()가 합리적인 결과를 얻지 못하는 것을 프로빙 할 수 있습니다. 이를 통해 zeros ()는 NaN을보고 작업을 계속할 수 있습니다.

NaN의 대안은 불법 작업 (신호 또는 트랩이라고도 함)이 발생하자마자 예외를 트리거하는 것입니다. 발생할 수있는 막대한 성능 저하 외에도 CPU가 하드웨어에서 CPU를 지원하거나 OS / 언어가 소프트웨어에서이를 지원한다는 보장은 없었습니다. 부동 소수점 처리에서 모두 고유 한 눈송이였습니다. IEEE는 소프트웨어에서 NaN 값으로 명시 적으로 처리하기로 결정하여 모든 OS 또는 프로그래밍 언어에서 이식 가능합니다. 올바른 부동 소수점 알고리즘은 일반적으로 node.js 또는 COBOL (hah)이든 모든 부동 소수점 구현 에서 정확 합니다.

이론적으로 특정 #pragma 지시문을 설정하거나, 미친 컴파일러 플래그를 설정하거나, 정확한 예외를 포착하거나, 특수한 신호 처리기를 설치하여 동일한 알고리즘으로 보이는 것이 실제로 올바르게 작동하도록 할 필요는 없습니다. 불행히도 일부 언어 디자이너와 컴파일러 작성자는이 기능을 최대한 활용하기 위해 바쁘게 일하고 있습니다.

IEEE 754 부동 소수점 이력에 대한 일부 정보를 읽으십시오. 또한위원회 회원이 응답 한 비슷한 질문에 대한이 답변 : IEEE754 NaN 값에 대해 거짓을 반환하는 모든 비교의 근거는 무엇입니까?

"부동 소수점 노인과의 인터뷰"

"IEEE 부동 소수점 형식의 역사"

부동 소수점 산술에 대해 모든 컴퓨터 과학자가 알아야 할 사항


음, log(-1)제공 NaNacos(2)제공도 NaN. 그 뜻 log(-1) == acos(2)입니까? 분명히 아닙니다. 따라서 NaN그 자체와 같지 않은 완벽한 의미가 있습니다.

거의 2 년 후에 다시 방문하면 다음과 같은 "NaN 안전"비교 기능이 있습니다.

function compare(a,b) {
    return a == b || (isNaN(a) && isNaN(b));
}

나의 원래의 대답 (4 년 전)은 결정의 맥락을 이해하지 않고 현대의 관점에서 결정을 비판합니다. 따라서 질문에 대답하지 않습니다.

정답은 다음과 같습니다 .

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

[...] isnan( )NaN이 8087 산술로 공식화 될 당시에는 술어 가 없었습니다 . isnan( )수년이 걸릴 수 있는 프로그래밍 언어에 의존하지 않는 NaN 값을 감지 할 수있는 편리하고 효율적인 수단을 프로그래머에게 제공 해야했습니다.

이 접근 방식에는 한 가지 단점이있었습니다. 수치 계산과 관련이없는 많은 상황에서 NaN의 유용성이 떨어졌습니다. 예를 들어, 나중에 사람들이 결 NaN측값을 나타 내기 위해 해시 기반 컨테이너에 넣기를 원했을 때 할 수 없었습니다.

위원회가 향후 사용 사례를 예측하고이를 충분히 중요하게 생각한다면에 대한 테스트 !(x<x & x>x)대신 더 자세한 정보를 얻을 수있었습니다 . 그러나 수치 계산에 가장 적합한 솔루션을 제공하는 방식으로 초점이보다 실용적이고 좁았습니다. 따라서 접근 방식에는 문제가 없었습니다.x!=xNaN

===

원래 답변 :

가장 투표가 많은 답변에 대한 생각을 고맙게 생각하기 때문에 미안합니다. NaN은 "정의되지 않음"을 의미하지 않습니다 . 7 페이지 http://www.cs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF 를 참조하십시오 ( "정의되지 않음"이라는 단어 검색). 그 문서가 확인 하듯이 NaN은 잘 정의 된 개념입니다.

또한 IEEE의 접근 방식은 일반적인 수학 규칙을 최대한 많이 따르는 것이 었으며, 그렇지 않은 경우 "최소한의 놀람"규칙을 따르십시오 ( https://stackoverflow.com/a/1573715/336527 참조) . 모든 수학적 객체는 그 자체와 동일하므로 수학 규칙은 NaN == NaN이 참이어야 함을 의미합니다. 나는 그러한 중요한 수학적 원리에서 벗어나는 타당하고 강력한 이유를 볼 수 없다 (비교의 삼 분류 술의 덜 중요한 규칙은 말할 것도 없다).

결과적으로 내 결론은 다음과 같습니다.

IEEE committee members did not think this through very clearly, and made a mistake. Since very few people understood the IEEE committee approach, or cared about what exactly the standard says about NaN (to wit: most compilers' treatment of NaN violates the IEEE standard anyway), nobody raised an alarm. Hence, this mistake is now embedded in the standard. It is unlikely to be fixed, since such a fix would break a lot of existing code.

Edit: Here is one post from a very informative discussion. Note: to get an unbiased view you have to read the entire thread, as Guido takes a different view to that of some other core developers. However, Guido is not personally interested in this topic, and largely follows Tim Peters recommendation. If anyone has Tim Peters' arguments in favor of NaN != NaN, please add them in comments; they have a good chance to change my opinion.


A nice property is: if x == x returns false, then x is NaN.

(one can use this property to check if x is NaN or not.)


Try this:

var a = 'asdf';
var b = null;

var intA = parseInt(a);
var intB = parseInt(b);

console.log(intA); //logs NaN
console.log(intB); //logs NaN
console.log(intA==intB);// logs false

If intA == intB were true, that might lead you to conclude that a==b, which it clearly isn't.

Another way to look at it is that NaN just gives you information about what something ISN'T, not what it is. For example, if I say 'an apple is not a gorilla' and 'an orange is not a gorilla', would you conclude that 'an apple'=='an orange'?


Actually, there is a concept in mathematics known as “unity” values. These values are extensions that are carefully constructed to reconcile outlying problems in a system. For example, you can think of ring at infinity in the complex plane as being a point or a set of points, and some formerly pretentious problems go away. There are other examples of this with respect to cardinalities of sets where you can demonstrate that you can pick the structure of the continuum of infinities so long as |P(A)| > |A| and nothing breaks.

DISCLAIMER: I am only working with my vague memory of my some interesting caveats during my math studies. I apologize if I did a woeful job of representing the concepts I alluded to above.

If you want to believe that NaN is a solitary value, then you are probably going to be unhappy with some of the results like the equality operator not working the way you expect/want. However, if you choose to believe that NaN is more of a continuum of “badness” represented by a solitary placeholder, then you are perfectly happy with the behavior of the equality operator. In other words, you lose sight of the fish you caught in the sea but you catch another that looks the same but is just as smelly.

참고URL : https://stackoverflow.com/questions/10034149/why-is-nan-not-equal-to-nan

반응형