Intel C++ 컴파일러에서 NaN - NaN == 0.0인 이유
NaNs가 산술적으로 전파한다는 것은 잘 알려져 있지만, 나는 어떤 시범도 찾을 수 없어서 다음과 같은 작은 시험을 썼다.
#include <limits>
#include <cstdio>
int main(int argc, char* argv[]) {
float qNaN = std::numeric_limits<float>::quiet_NaN();
float neg = -qNaN;
float sub1 = 6.0f - qNaN;
float sub2 = qNaN - 6.0f;
float sub3 = qNaN - qNaN;
float add1 = 6.0f + qNaN;
float add2 = qNaN + qNaN;
float div1 = 6.0f / qNaN;
float div2 = qNaN / 6.0f;
float div3 = qNaN / qNaN;
float mul1 = 6.0f * qNaN;
float mul2 = qNaN * qNaN;
printf(
"neg: %f\nsub: %f %f %f\nadd: %f %f\ndiv: %f %f %f\nmul: %f %f\n",
neg, sub1,sub2,sub3, add1,add2, div1,div2,div3, mul1,mul2
);
return 0;
}
(여기서 라이브로 실행)의 예는 기본적으로 내가 기대했던 것을 생산한다(부정적인 것은 약간 이상하지만, 좀 말이 된다).
neg: -nan
sub: nan nan nan
add: nan nan
div: nan nan nan
mul: nan nan
MSVC 2015는 비슷한 것을 생산한다.그러나 Intel C++ 15는 다음을 생산한다.
neg: -nan(ind)
sub: nan nan 0.000000
add: nan nan
div: nan nan nan
mul: nan nan
구체적으로 말하자면qNaN - qNaN == 0.0
.
이럴 순 없지?이에 대해 관련 표준(ISO C, ISO C++, IEEE 754)은 뭐라고 말하고 있으며, 컴파일러 간 동작에 차이가 있는 이유는 무엇인가?
Intel C++ 컴파일러의 기본 부동 소수점 처리 방식은/fp:fast
, 어느 것이 취급하는가NaN
의 안전하지 않은 (결과도 있음)NaN == NaN
존재true
예를 들어).지정 시도/fp:strict
또는/fp:precise
그게 도움이 되는지 알아봐줘
이건... 맞지?제 질문: 관련 표준(ISO C, ISO C++, IEEE 754)은 이에 대해 뭐라고 하는가?
페트르 압둘린은 컴파일러가 왜 a를 주는지 이미 대답했다.0.0
대답하다
IEEE-754:2008의 내용은 다음과 같다.
(6.2 NaNs를 사용한 운영) "[...] 최대 및 최소 운영 이외의 조용한 NaN 입력이 있는 작업의 경우, 부동 소수점 결과가 전달될 경우 결과는 입력 NaN 중 하나가 되어야 하는 조용한 NaN이어야 한다."
따라서 두 개의 조용한 NaN 피연산자의 뺄셈에 대한 유일한 유효한 결과는 조용한 NaN이다. 다른 결과는 유효하지 않다.
C Standard에 따르면 다음과 같다.
(C11, F.9.2 식 변환 p1) "[...]
x - x → 0 "x가 NaN이거나 무한인 경우 x - x와 0은 등가물이 아니다."
(여기서 NaN은 F.2.1p1 "이 규격은 NaNs 신호를 보내는 동작을 정의하지 않는다.그것은 일반적으로 조용한 NaN을 나타내기 위해 NaN이라는 용어를 사용한다.)
나는 인텔 컴파일러의 표준 준수를 비난하는 답을 보고 있고, 아무도 이것을 언급하지 않았기 때문에, GCC와 캉 모두 상당히 비슷한 일을 하는 모드를 가지고 있다는 것을 지적할 것이다.기본 동작은 IEEE 호환 -
$ g++ -O2 test.cc && ./a.out
neg: -nan
sub: nan nan nan
add: nan nan
div: nan nan nan
mul: nan nan
$ clang++ -O2 test.cc && ./a.out
neg: -nan
sub: -nan nan nan
add: nan nan
div: nan nan nan
mul: nan nan
— 하지만 정확성을 희생하여 속도를 요구하면 원하는 것을 얻을 수 있다.
$ g++ -O2 -ffast-math test.cc && ./a.out
neg: -nan
sub: nan nan 0.000000
add: nan nan
div: nan nan 1.000000
mul: nan nan
$ clang++ -O2 -ffast-math test.cc && ./a.out
neg: -nan
sub: -nan nan 0.000000
add: nan nan
div: nan nan nan
mul: nan nan
나는 ICC의 채무 불이행 선택을 비판하는 것이 전적으로 타당하다고 생각하지만, 나는 유닉스 전쟁 전체를 다시 그 결정으로 되돌리지는 않을 것이다.
참조URL: https://stackoverflow.com/questions/32195949/why-does-nan-nan-0-0-with-the-intel-c-compiler
'IT이야기' 카테고리의 다른 글
자바에서 바이트 배열을 16진수로 변환하는 방법? (0) | 2022.05.26 |
---|---|
index.html이 Javascript를 로드하지 않을 경우 Vue 앱을 실행하는 방법은? (0) | 2022.05.26 |
구성요소 렌더 함수에 무한 업데이트 루프가 있을 수 있음 (0) | 2022.05.26 |
리사이클러 보기 어댑터에서 컨텍스트를 가져오는 방법 (0) | 2022.05.26 |
Vuelidate 날짜 입력 필드 (0) | 2022.05.26 |