C ++에서 double (또는 float)이 NaN인지 확인


368

isnan () 함수가 있습니까?

추신 : 나는 MinGW에 있습니다 (차이가있는 경우).

나는이 ()에서 때는 isNaN을 사용하여 해결 한 <math.h>에서 존재하지 않는, <cmath>내가 한, #include처음에 보내고.


2
순전히 당신이 그것을 할 수있는 것은 아닙니다. C ++에 IEEE754가 필요하다고 누가 말합니까?
David Heffernan


참고로, 1 온스의 예방이 1 파운드의 치료보다 낫습니다. 다시 말해, 0.f / 0.f가 실행되는 것을 막는 것이 nan코드에서 를 소급하여 확인하는 것보다 훨씬 낫습니다 . nan는 프로그램을 심각하게 파괴 할 수 있습니다. 이는 nan독성 (5 * nan= nan) nan이 다른 것 ( nan! = nan)과 nan같지 않으며 , 어떤 것 ( nan!> 0) nan보다 크지 않은 것 ( nan! <0) 이기 때문 입니다.
bobobobo

1
@bobobobo : 중앙 집중식 오류 검사를 허용하는 기능입니다. 예외 대 반환 값과 마찬가지로.
벤 Voigt

2
<cmath>에 isnan ()이없는 이유는 무엇입니까? std ::
frankliuao

답변:


349

IEEE 표준에 따르면 NaN 값은 값과 관련된 비교가 항상 거짓 이라는 이상한 속성을 갖습니다 . 즉, float f의 f != f경우 사실입니다. , f는 NaN의 경우.

아래의 일부 의견에서 지적했듯이 모든 컴파일러가 코드를 최적화 할 때 이것을 존중하지는 않습니다.

IEEE 부동 소수점을 사용한다고 주장하는 컴파일러의 경우이 트릭 작동합니다. 그러나 나는 그것을 보장 할 수 없습니다 것입니다 실제로 작동합니다. 의심스러운 경우 컴파일러에 문의하십시오.


4
IEEE 모드에서 실행하는 경우 컴파일러에서이를 제거하지 않는 것이 좋습니다. 물론 컴파일러의 문서를 확인하십시오.
dmckee --- 전 운영자 고양이 새끼 고양이

38
-1은 이론적으로 만 작동하지만 실제로는 아닙니다. g ++ (-fastmath 포함)와 같은 컴파일러는이를 망칩니다. c ++ 0x까지 유일한 일반적인 방법은 비트 패턴을 테스트하는 것입니다.
건배와 hth. -Alf

66
@Alf : -ffast-math옵션에 대한 문서는 IEEE 또는 ISO가 수학 함수에 대한 규칙 / 사양 인 경우 정확한 구현에 의존하는 프로그램에 대해 잘못된 출력을 초래할 수 있다고 명시 적으로 명시하고 있습니다. 이 옵션을 사용하지 않으면, 사용 x != x은 NaN을위한 완벽하고 유효하며 이식 가능한 테스트 방법입니다.
Adam Rosenfield

7
@ 아담 : 문서에는 공개 문서가 부적합하다고 명시되어 있습니다. 그리고 예, 가브리엘 도스 라이스 (Gabriel Dos Reis)와이 문제에 대해 오랫동안 논의하면서 그 주장에 직면했습니다. 그것은 일반적으로 순환 논쟁에서 디자인을 방어하는 데 사용됩니다 (나는 당신이 그것에 연관시킬 의도는 모르지만 그것에 대해 알 가치가 있습니다-불꽃 전쟁 물건입니다). x != x해당 옵션없이 유효한 결론 은 논리적으로 따르지 않습니다. g ++의 특정 버전에 해당 될 수도 있고 그렇지 않을 수도 있습니다. 어쨌든 일반적으로 fastmath 옵션이 사용되지 않도록 보장 할 방법이 없습니다.
건배와 hth. -Alf

7
@Alf : 아니요 Gabriel Dos Reis와의 토론에 대해서는 몰랐습니다. Steve Jessop은 IEEE 표현 가정에 관한 다른 질문에서 큰 지적을했습니다. IEEE 754를 가정하고 컴파일러가 적합한 방식으로 (즉, -ffast-math옵션 없이) 작동한다고 가정 x != x하면 유효하고 이식 가능한 솔루션입니다. 매크로 -ffast-math를 테스트하여 테스트 할 수도 __FAST_MATH__있고이 경우 다른 구현으로 전환 할 수도 있습니다 (예 : 공용체 및 비트 트위들 링 사용).
Adam Rosenfield 2016 년

220

isnan()현재 C ++ 표준 라이브러리 에는 사용 가능한 기능 이 없습니다 . C99 에 도입되어 매크로 로 정의되었습니다. 함수가 아닌 . C99로 정의 된 표준 라이브러리 요소는 현재 C ++ 표준 ISO / IEC 14882 : 1998의 일부가 아니며 업데이트 ISO / IEC 14882 : 2003도 아닙니다.

2005 년에는 기술 보고서 ​​1이 제안되었습니다. TR1은 C99와 C ++의 호환성을 제공합니다. 실제로는 C ++ 표준이되기 위해 공식적으로 채택 된 적이 없지만 많은 ( GCC 4.0+ 또는 Visual C ++ 9.0+ C ++ 구현은 TR1 기능을 제공하거나, 전부 또는 일부만 제공합니다 (Visual C ++ 9.0은 C99 수학 함수를 제공하지 않음) .

TR1 사용할 수있는 경우, 다음 cmath과 같은 C99 요소를 포함 isnan(), isfinite()등을하지만, 일반적으로 함수가 아니라 매크로로 정의되어 std::tr1::, 네임 스페이스하지만 그 주사한다 (맥 OS X 10.5에서 엑스 코드 리눅스 또는 즉, GCC 4+) 많은 구현 로 직접 정의 std::되므로 std::isnan잘 정의됩니다.

또한, C의 일부 구현 ++ 여전히 C99 만들 isnan()(를 포함 ++ C 매크로 사용할 수 cmath또는 math.h더 혼란과 개발자들이이 표준 동작입니다 가정 할 수의 원인이 무엇인지,).

Viusal C ++에 대한 참고 사항은 위에서 언급 한 것처럼 std::isnan어느 것도 제공 하지 std::tr1::isnan않지만 _isnan()이후에 사용 가능한 것으로 정의 된 확장 함수를 제공합니다 Visual C ++ 6.0

XCode에는 더 많은 재미가 있습니다. 언급했듯이 GCC 4+는을 정의합니다 std::isnan. 이전 버전의 컴파일러 및 라이브러리 XCode 형식의 경우 Intel 및 Power PC 에 두 가지 기능이 정의 되어있는 것 같습니다 (여기서는 관련 토론이 있습니다 ) .__inline_isnand()__isnand()


21
모두 isNan 또는 isInfinity와 같은 이러한 기능을 원합니다. 담당자가 단순히 표준에 포함시키지 않는 이유는 무엇입니까 ???? -나는 어떻게 책임을지고 이에 대한 투표를하는지 알아볼 것이다. 진심으로.
shuhalo

8
@shuhalo 아직 담당?
Tomáš Zato-복권 모니카

11
이 답변 std::isnan은 이제 C ++ 11 표준의 일부이며 지원이 확산되었으므로 업데이트해야합니다 . std :: isnan은 Visual Studio 2013부터 Visual Studio에서 구현되었습니다. 아마도 @shuhalo가 담당했습니다 :-)
aberaud

170

첫 번째 해결책 : C ++ 11을 사용하는 경우

이것이 요청 되었기 때문에 약간의 새로운 개발이있었습니다. 그것이 std::isnan()C ++ 11의 일부 임을 아는 것이 중요합니다

개요

헤더에 정의 <cmath>

bool isnan( float arg ); (since C++11)
bool isnan( double arg ); (since C++11)
bool isnan( long double arg ); (since C++11)

주어진 부동 소수점 숫자 arg가 숫자가 아닌지 판별합니다 (NaN ).

매개 변수

arg: 부동 소수점 값

반환 값

truearg가 인 NaN경우false 경우 그렇지 않은 경우

참고

http://en.cppreference.com/w/cpp/numeric/math/isnan

g ++를 사용하는 경우 -fast-math와 호환되지 않습니다. 다른 제안 사항은 아래를 참조하십시오.


다른 솔루션 : 비 C ++ 11 호환 도구를 사용하는 경우

C99의 경우 C에서는 isnan(c)int 값을 반환하는 매크로로 구현됩니다 . 유형은 xfloat, double 또는 long double이어야합니다.

다양한 벤더가 기능을 포함하거나 포함하지 않을 수 있습니다 isnan().

추측하기 쉬운 휴대용 방법 NaN은 IEEE 754 속성을 사용 NaN하지 않는 것입니다. 즉, x == xfalse 인 xNaN입니다.

그러나 마지막 옵션은 모든 컴파일러 및 일부 설정 (특히 최적화 설정)에서 작동하지 않을 수 있으므로 최후의 수단으로 항상 비트 패턴을 확인할 수 있습니다 ...


8
확실히 대답할만한 가치가 있으며 더 많은 투표를받을 가치가 있습니다. 팁 주셔서 감사합니다
LBes

3
−1 std::isnan 은 g ++의 부동 소수점 최적화와 함께 작동하지 않으므로 2017 년 2 월 현재 권장되지 않습니다.
건배와 hth. -Alf

@ Cheersandhth.-Alf :이 옵션은 IEEE 호환입니까? 대답은 편집 된
BlueTrin

@BlueTrin은 : 모두 x != xisnanIEEE 754 준수를위한 작업에 필요합니다. 후자에 관해, IEEE 754-2008 표준은 "구현은 지원되는 모든 산술 형식에 대해 다음과 같은 비계산 연산을 제공해야하며" "x가 NaN 인 경우에만 isNaN (x)가 참"이라고 명시하고 있습니다. 표준이 요구하는 적합성을 확인하기위한 is754version1985()is754version2008()C ++ 대신 제공하는 경우, std::numeric_limits<Fp>::is_iec559()(IEC 559은 동일한 표준입니다). 불행히도 -ffast-mathg ++ 클레임 준수 와 같은 최적화에서는 적합하지 않습니다.
건배와 hth. -Alf

1
경고 : isnan (x)는 gcc와 clang에서 -ffinite-math-only 옵션과 함께 작동하지 않습니다
Fog

82

도있다 헤더 전용 라이브러리 부동 소수점 데이터 유형을 처리하는 깔끔한 도구가 부스트에 존재하는

#include <boost/math/special_functions/fpclassify.hpp>

다음과 같은 기능이 있습니다.

template <class T> bool isfinite(T z);
template <class T> bool isinf(T t);
template <class T> bool isnan(T t);
template <class T> bool isnormal(T t);

시간이 있다면 Boost의 전체 Math 툴킷을 살펴보면 유용한 도구가 많이 있으며 빠르게 성장하고 있습니다.

또한 부동 소수점과 비 부동 소수점을 다룰 때 Numeric Conversions 를 보는 것이 좋습니다 .


1
감사! 내가 찾던 것.
Dr. Watson

그것은 Boost 1.35에 추가되었습니다 (방금 내 프로그램이 오래된 Linux 배포판에서 컴파일되지 않는다는 것을 알았습니다).
marcin

2
--fast-math 옵션으로 컴파일하면이 함수가 예상대로 작동하지 않습니다.
Gaetano Mendola

43

posix isnan매크로 , c ++ 0x isnan함수 템플릿 또는 시각적 c ++ _isnan함수의 세 가지 "공식적인"방법이 있습니다 .

불행히도 어떤 것을 사용할지를 감지하는 것은 비현실적입니다.

불행히도 NaN으로 IEEE 754 표현이 있는지 여부를 감지 할 수있는 확실한 방법은 없습니다. 표준 라이브러리는 공식적인 방법을 제공합니다 (numeric_limits<double>::is_iec559 ). 그러나 실제로 g ++와 같은 컴파일러는 그것을 망칩니다.

이론적으로는 간단하게 사용할 수 x != x있지만 g ++ 및 시각적 c ++와 같은 컴파일러는이를 강화시킵니다.

결국에는 IEEE 754와 같은 특정 표현을 가정하고 특정 시점에서 시행 할 특정 NaN 비트 패턴을 테스트하십시오 .


편집 : "g ++…와 같은 컴파일러와 같은 컴파일러"의 예로서, 고려하십시오

#include <limits>
#include <assert.h>

void foo( double a, double b )
{
    assert( a != b );
}

int main()
{
    typedef std::numeric_limits<double> Info;
    double const nan1 = Info::quiet_NaN();
    double const nan2 = Info::quiet_NaN();
    foo( nan1, nan2 );
}

g ++로 컴파일 (TDM-2 mingw32) 4.4.1 :

C : \ test> 유형 "C : \ Program Files \ @commands \ gnuc.bat"
@rem -finput-charset = windows-1252
@ g ++ -O -pedantic -std = c ++ 98-벽-쓰기 문자열 % *-롱 롱

C : \ test> gnuc x.cpp

C : \ test> && echo 작동 ... || 에코! 실패
공장...

C : \ test> gnuc x.cpp --fast-math

C : \ test> && echo 작동 ... || 에코! 실패
어설 션 실패 : a! = b, 파일 x.cpp, 6 행

이 응용 프로그램은 런타임을 비정상적인 방식으로 종료하도록 요청했습니다.
자세한 내용은 응용 프로그램 지원 팀에 문의하십시오.
!실패한

C : \ test> _

4
@ Alf : 귀하의 예제는 4.0과 4.5 사이의 다양한 버전의 g ++에서 Mac OS X과 Linux 모두에서 예상대로 작동합니다. 이 -ffast-math옵션에 대한 설명서에는 수학 함수에 대한 IEEE 또는 ISO 규칙 / 사양 인 경우 정확한 구현에 의존하는 프로그램에 대해 잘못된 출력이 발생할 수 있다고 명시되어 있습니다. 이 옵션을 사용하지 않으면, 사용 x != x은 NaN을위한 완벽하고 유효하며 이식 가능한 테스트 방법입니다.
Adam Rosenfield

6
@ 아담 : 당신이 빠진 것은 C ++ 표준에 수레에 대한 IEEE 표현이나 수학이 필요하지 않다는 것입니다. 지금까지 사람의 페이지, 당신을 알려줍니다으로 gcc -ffast-math(이 도착 가정도 여전히 준수하는 C ++ 구현 numeric_limits::is_iec559알프 그것을하지 않는 이상 알 수 있지만, 그것이 오른쪽) : C ++ IEEE에 의존하는 코드가 없는 휴대용 C ++와 권리가 없다 구현이 그것을 제공 할 것으로 기대합니다.
Steve Jessop

5
그리고 gcc 4.3.4에 대한 Alf의 옳고 빠른 테스트 is_iec559이며 -ffast-math. 따라서 여기서 문제는 GCC의 문서는 -ffast-math수학 함수의 경우 IEEE / ISO 아니라고 말하는 반면 , 구현 numeric_limits이 중단되었으므로 C ++ 아니라고 말하는 것 입니다. 최종 백엔드에 실제로 플로팅이 있는지 여부에 따라 템플릿을 정의 할 때 GCC가 항상 알 수있는 것은 아니라고 생각하지도 않습니다. IIRC는 GCC의 C99 적합성에 대한 뛰어난 버그 목록에 비슷한 문제가 있습니다.
Steve Jessop

1
@Alf, @Steve, C ++ 표준에는 부동 소수점 값에 대한 사양이 없습니다. 꽤 충격적입니다. IEEE 754 및 NaN을 표준 대신 플랫폼 별 확장으로 처리하는 것이 좋습니다. 그렇지 않습니까? 그리고 C ++ 0x에 어떤 종류의 isnan () 또는 IEEE754가 추가 될 것으로 기대할 수 있습니까?
Eonil

3
@Eonil : C ++ 0x에는 여전히 "소수점 유형의 값 표현이 구현 정의되어 있습니다"가 있습니다. C와 C ++는 모두 부동 소수점 하드웨어가없는 머신에서 구현을 지원하는 것을 목표로하며, 적절한 IEEE 754 플로트는 합리적으로 정확한 대안보다 에뮬레이션하기가 상당히 느릴 수 있습니다. 이론은 is_iec559실제로 GCC에서 작동하지 않는 것으로 보이는 IEEE가 필요한 경우 주장 할 수 있다는 것입니다. C ++ 0x에는 isnan함수가 있지만 GCC가 is_iec559현재 올바르게 구현되지 않았으므로 C ++ 0x에 포함되지 않으며 -ffast-math잘 깨질 수 있습니다 isnan.
Steve Jessop

39

컴파일러가 c99 확장을 지원하면 std :: isnan이 있지만 mingw가 지원하는지 확실하지 않습니다.

컴파일러에 표준 함수가없는 경우 작동해야하는 작은 함수가 있습니다.

bool custom_isnan(double var)
{
    volatile double d = var;
    return d != d;
}

6
왜 var! = var가 아닌가?
Brian R. Bondy

8
그렇게 할 때 컴파일러는 비교를 최적화하고 항상 true를 반환합니다.
CTT

23
없습니다. 이를 수행하는 컴파일러가 손상되었습니다. 표준 라이브러리 isnan가 잘못된 결과를 반환 할 가능성이 있다고 말할 수도 있습니다. 기술적으로 사실, 컴파일러 버그 일 수 있지만 실제로는 Gonna Happen이 아닙니다. 와 동일합니다 var != var. 그것이 IEEE 부동 소수점 값이 정의되는 방식이기 때문에 작동합니다.
jalf

29
-ffast-math가 설정되면 isnan ()은 gcc에 대한 올바른 결과를 반환하지 않습니다. 물론,이 최적화는 IEEE 의미를 깨뜨리는 것으로 문서화되어 있습니다.
Matthew Herrmann

-ffast-math가 설정되면 컴파일러는 버그가있는 것입니다. 또는 오히려 -ffast-math가 설정되면 모든 베팅이 해제되고 NaN에 의존 할 수 없습니다.
Adrian Ratnapala

25

표준 라이브러리에 numeric_limits<float>::quiet_NaN( )정의 된 것을 사용 limits하여 테스트 할 수 있습니다 . 에 대해 별도의 상수가 정의되어 double있습니다.

#include <iostream>
#include <math.h>
#include <limits>

using namespace std;

int main( )
{
   cout << "The quiet NaN for type float is:  "
        << numeric_limits<float>::quiet_NaN( )
        << endl;

   float f_nan = numeric_limits<float>::quiet_NaN();

   if( isnan(f_nan) )
   {
       cout << "Float was Not a Number: " << f_nan << endl;
   }

   return 0;
}

Linux에서 g ++로만 테스트 했으므로 이것이 모든 플랫폼에서 작동하는지 모르겠습니다.


2
그러나 GCC 버전 3.2.3에서는 numeric_limits에 버그가있는 것으로 보입니다. quiet_NaN의 경우 0.0을 반환하기 때문입니다. GCC의 나중 버전은 제 경험상 괜찮습니다.
Nathan Kitchen

@Nathan : 알아두면 좋습니다. 버전 4.3.2를 사용하고 있으므로 숲에서 벗어나 있습니다.
Bill the Lizard

18

isnan()함수 를 사용할 수 있지만 C 수학 라이브러리를 포함해야합니다.

#include <cmath>

이 기능은 C99의 일부이므로 일부 지역에서는 사용할 수 없습니다. 공급 업체가 기능을 제공하지 않으면 호환성을 위해 고유 한 변형을 정의 할 수도 있습니다.

inline bool isnan(double x) {
    return x != x;
}

나는 <cmath>를 사용하고 있었고 거기에는 isnan이 없습니다! 우연히 내가 거기 있다는 것을 발견 이다isnan 에서 <math.h>
하센

1
내가 말했듯이, 이것은 C99의 일부입니다. C99는 현재 C ++ 표준의 일부가 아니므로 대안을 제공했습니다. 그러나 isnan ()이 다가오는 C ++ 표준에 포함될 가능성이 있으므로 #ifndef 지시어를 사용합니다.
raimue

12

다음 코드는 NAN (모든 지수 비트 세트, 하나 이상의 소수 비트 세트)의 정의를 사용하며 sizeof (int) = sizeof (float) = 4라고 가정합니다. 자세한 내용은 Wikipedia에서 NAN을 조회 할 수 있습니다.

bool IsNan( float value ) { return ((*(UINT*)&value) & 0x7fffffff) > 0x7f800000; }


나는 이것이 빅 엔디안 플랫폼에서도 작동한다고 생각합니다. 리터럴 0x7fffffff은 단순히 메모리에 다음과 같이 앉아 있습니다 ff ff ff 7f. value와 동일한 순서를 가지 0x7f800000므로 모든 작업이 정렬됩니다 (바이트 교체 없음). 누군가가 큰 엔디안 플랫폼에서 이것을 테스트 할 수 있다면 관심이 있습니다.
Bryan W. Wagner

0x7fff1234NaN이기도합니다. 그래서이다0xffffffff
스티브 Hollasch

12

난 예방

이 질문에 대한 나의 대답은에 대한 소급 확인을 사용하지 않습니다nan . 대신 양식 구분에 대한 예방 점검을 사용하십시오 0.0/0.0.

#include <float.h>
float x=0.f ;             // I'm gonna divide by x!
if( !x )                  // Wait! Let me check if x is 0
  x = FLT_MIN ;           // oh, since x was 0, i'll just make it really small instead.
float y = 0.f / x ;       // whew, `nan` didn't appear.

nan작업 결과 0.f/0.f또는 0.0/0.0. nan감지해야한다 코드의 안정에 무서운 천적이다 방지 매우 신중 1 . 그 속성은 nan일반 숫자와 다릅니다.

  • nan독성이 있으며 (5 * nan= nan)
  • nan아무것도 아니고, 그 자체도 아니다 ( nan! = nan)
  • nan무엇보다 크지 않음 ( nan!> 0)
  • nan무엇보다 중요하지 않습니다 ( nan! <0)

나열된 마지막 2 개의 속성은 반론 적이며 nan숫자 와의 비교에 의존하는 코드의 이상한 동작을 초래합니다 (마지막 세 번째 속성도 홀수이지만 x != x ?코드에서 볼 수는 없습니다 (확인하지 않는 한) nan (믿을 수 없음))).

내 코드에서는 nan값이 버그를 찾기가 어렵다는 것을 알았 습니다. (이게 얼마나 참고 하지 의 경우 inf-inf. ( -inf<0) 반환 TRUE, (0 < inf) TRUE를 반환, 심지어 ( -inf< inf) TRUE를 반환합니다. 그래서, 내 경험, 코드의 동작은 종종 원하는대로 여전히).

난에서해야 할 일

당신이하고 싶은 0.0/0.0 것은 특별한 경우로 처리되어야 하지만, 당신이하는 일은 코드에서 나오는 숫자에 달려 있어야합니다.

위의 예에서 ( 0.f/FLT_MIN) 의 결과는 0기본적으로입니다. 대신 0.0/0.0생성 할 수 있습니다 HUGE. 그래서,

float x=0.f, y=0.f, z;
if( !x && !y )    // 0.f/0.f case
  z = FLT_MAX ;   // biggest float possible
else
  z = y/x ;       // regular division.

따라서 위의 경우 x가 0.f이면 inf결과가 실제로 나타납니다 (실제로 위에서 언급했듯이 아주 좋고 비파괴적인 행동을합니다).

기억 0으로 정수 부문은 런타임 예외가 발생합니다 . 따라서 항상 0으로 정수 나누기를 점검해야합니다. 0.0/0.0조용히 평가 nan한다고해서 게으르고 0.0/0.0발생하기 전에 점검 할 수있는 것은 아닙니다 .

1 via 검사 는 때때로 신뢰할 수 없습니다 ( 특히 스위치가 활성화 된 경우 IEEE 준수를 위반하는 일부 최적화 컴파일러에 의해 제거됨 ).nanx != xx != x-ffast-math


이것을 지적 해 주셔서 감사합니다. 그런 프로그래밍은 분명히 문제에 도움이 될 것입니다. 그러나 다음에는 텍스트 서식 기능을 너무 많이 남용하지 마십시오. 글꼴 크기, 무게 및 스타일을 바꾸면 읽기가 어렵습니다.
Magnus

4
NaN을 초래할 수있는 유일한 작업은 0.0 / 0.0이 아닙니다. 음수의 제곱근은 NaN을 반환합니다. + infinity의 코사인은 NaN도 반환합니다. x가 [0, pi] 범위에 있지 않은 acos (x) 연산은 NaN을 초래할 수도 있습니다. 간단히 말해서 0.0 / 0.0뿐만 아니라 이러한 잠재적으로 위험한 작업을 살펴 ​​보는 데에도주의를 기울여야합니다.
Boris Dalstein

보리스와 전적으로 동의합니다. 내 경험상 NaN은 실제로 항상 sqrt (-1.302e-53)와 같은 것에서 나온 것입니다. 즉, 0에 가까운 중간 계산 결과가 부정성을 확인하지 않고 sqrt에 제공됩니다.
hans_meine

1
"NaN 방지"는 나눗셈뿐만 아니라 모든 기본 산술 연산을 수행해야 함을 의미합니다. ∞ / ∞, 0 * ∞, ∞ % x, x % 0, ∞-∞, 0 ^ 0, ∞ ^ 0에 대해 조심해야합니다. 이러한 기본적인 산술 연산으로 "예방 적"이라는 것은 성능을 완전히 향상 시키며 생각하지 않은 추가 사례를 놓칠 수 있음을 의미합니다.
Steve Hollasch 1

11

C ++ 14에서 부동 소수점 숫자 value가 NaN 인지 테스트하는 방법에는 여러 가지가 있습니다.

이 방법들 중에서 , 숫자의 표현 비트검사하는 것은 원래의 대답에서 언급했듯이 안정적으로 작동합니다. 특히, std::isnan자주 제안되는 check v != v, 누군가가 부동 소수점 최적화가 필요하다고 결정할 때 코드가 올바르게 작동하지 않도록 컴파일러가 안정적으로 작동하지 않아야하며 사용해서는 안됩니다. 이 상황은 바뀔 수 있고 컴파일러는 더 잘 적응할 수 있지만 원래의 대답 이후 6 년 동안 발생하지 않은이 문제에 대해.

약 6 년 동안 제 원래의 대답은이 질문에 대한 선택된 솔루션이었습니다. 그러나 최근 신뢰할 수없는 v != v테스트를 추천하는 높은 평가를받은 답변 이 선택되었습니다. 따라서이 추가 최신 답변 (현재 C ++ 11 및 C ++ 14 표준과 C ++ 17이 있습니다).


C ++ 14에서 NaN-ness를 확인하는 주요 방법은 다음과 같습니다.

  • std::isnan(value) )
    C ++ 11 이후로 의도 된 표준 라이브러리 방식입니다. isnan분명히 같은 이름의 Posix 매크로와 충돌하지만 실제로는 문제가되지 않습니다. 주요 문제는 부동 소수점 산술 최적화가 요청 된 경우 하나 이상의 기본 컴파일러, 즉 g ++를 사용 하여 NaN 인수를 std::isnan 반환false 한다는 것 입니다.

  • (fpclassify(value) == FP_NAN) )
    와 같은 문제로 어려움을 겪습니다 std::isnan. 즉, 신뢰할 수 없습니다.

  • (value != value) )
    많은 SO 답변에서 권장됩니다. 와 같은 문제로 어려움을 겪습니다 std::isnan. 즉, 신뢰할 수 없습니다.

  • (value == Fp_info::quiet_NaN()) )
    이것은 표준 동작을 사용하여 NaN을 감지해서는 안되지만 최적화 된 동작을 사용하면 (비트 레벨 표현을 직접 비교하는 최적화 된 코드로 인해) NaN을 감지 할 수 있으며 다른 방법과 결합하여 최적화되지 않은 표준 동작을 처리 할 수 ​​있습니다 NaN을 안정적으로 감지 할 수 있습니다. 불행히도 그것은 안정적으로 작동하지 않는 것으로 나타났습니다.

  • (ilogb(value) == FP_ILOGBNAN) )
    와 같은 문제로 어려움을 겪습니다 std::isnan. 즉, 신뢰할 수 없습니다.

  • isunordered(1.2345, value) )
    와 같은 문제로 어려움을 겪습니다 std::isnan. 즉, 신뢰할 수 없습니다.

  • is_ieee754_nan( value ) )
    이것은 표준 기능이 아닙니다. IEEE 754 표준에 따라 비트를 확인합니다. 완전히 신뢰할 만하지 코드는 시스템에 따라 다릅니다.


다음의 완전한 테스트 코드에서 "성공"은 표현식이 값의 난을보고하는지 여부입니다. 대부분의 표현에서이 성공 척도 인 NaN과 NaN 만 탐지한다는 목표는 표준 시맨틱에 해당합니다. 를 들어 (value == Fp_info::quiet_NaN()) )표현하지만, 표준 동작은이 할머니 검출기로 작동하지 않습니다.

#include <cmath>        // std::isnan, std::fpclassify
#include <iostream>
#include <iomanip>      // std::setw
#include <limits>
#include <limits.h>     // CHAR_BIT
#include <sstream>
#include <stdint.h>     // uint64_t
using namespace std;

#define TEST( x, expr, expected ) \
    [&](){ \
        const auto value = x; \
        const bool result = expr; \
        ostringstream stream; \
        stream << boolalpha << #x " = " << x << ", (" #expr ") = " << result; \
        cout \
            << setw( 60 ) << stream.str() << "  " \
            << (result == expected? "Success" : "FAILED") \
            << endl; \
    }()

#define TEST_ALL_VARIABLES( expression ) \
    TEST( v, expression, true ); \
    TEST( u, expression, false ); \
    TEST( w, expression, false )

using Fp_info = numeric_limits<double>;

inline auto is_ieee754_nan( double const x )
    -> bool
{
    static constexpr bool   is_claimed_ieee754  = Fp_info::is_iec559;
    static constexpr int    n_bits_per_byte     = CHAR_BIT;
    using Byte = unsigned char;

    static_assert( is_claimed_ieee754, "!" );
    static_assert( n_bits_per_byte == 8, "!" );
    static_assert( sizeof( x ) == sizeof( uint64_t ), "!" );

    #ifdef _MSC_VER
        uint64_t const bits = reinterpret_cast<uint64_t const&>( x );
    #else
        Byte bytes[sizeof(x)];
        memcpy( bytes, &x, sizeof( x ) );
        uint64_t int_value;
        memcpy( &int_value, bytes, sizeof( x ) );
        uint64_t const& bits = int_value;
    #endif

    static constexpr uint64_t   sign_mask       = 0x8000000000000000;
    static constexpr uint64_t   exp_mask        = 0x7FF0000000000000;
    static constexpr uint64_t   mantissa_mask   = 0x000FFFFFFFFFFFFF;

    (void) sign_mask;
    return (bits & exp_mask) == exp_mask and (bits & mantissa_mask) != 0;
}

auto main()
    -> int
{
    double const v = Fp_info::quiet_NaN();
    double const u = 3.14;
    double const w = Fp_info::infinity();

    cout << boolalpha << left;
    cout << "Compiler claims IEEE 754 = " << Fp_info::is_iec559 << endl;
    cout << endl;;
    TEST_ALL_VARIABLES( std::isnan(value) );                    cout << endl;
    TEST_ALL_VARIABLES( (fpclassify(value) == FP_NAN) );        cout << endl;
    TEST_ALL_VARIABLES( (value != value) );                     cout << endl;
    TEST_ALL_VARIABLES( (value == Fp_info::quiet_NaN()) );      cout << endl;
    TEST_ALL_VARIABLES( (ilogb(value) == FP_ILOGBNAN) );        cout << endl;
    TEST_ALL_VARIABLES( isunordered(1.2345, value) );           cout << endl;
    TEST_ALL_VARIABLES( is_ieee754_nan( value ) );
}

g ++로 결과 (표준 동작은 (value == Fp_info::quiet_NaN())NaN 검출기로 작동하지 않는다는 것입니다. 실제적으로 관심이 많습니다).

[C : \ my \ 포럼 \ so \ 282 (NaN 감지)]
> g ++-버전 | "++"찾기
g ++ (x86_64-win32-sjlj-rev1, MinGW-W64 프로젝트에 의해 빌드 됨) 6.3.0

[C : \ my \ 포럼 \ so \ 282 (NaN 감지)]
> g ++ foo.cpp && a
컴파일러, IEEE 754 = 클레임

v = nan, (std :: isnan (value)) = true 성공
u = 3.14, (std :: isnan (value)) = 거짓 성공
w = inf, (std :: isnan (value)) = 거짓 성공

v = nan, ((fpclassify (value) == 0x0100)) = true 성공
u = 3.14, ((fpclassify (value) == 0x0100)) = 거짓 성공
w = inf, ((fpclassify (value) == 0x0100)) = 거짓 성공

v = nan, ((value! = value)) = true 성공
u = 3.14, ((value! = value)) = 거짓 성공
w = inf, ((value! = value)) = 거짓 성공

v = nan, ((value == Fp_info :: quiet_NaN ())) = 거짓 FAILED
u = 3.14, ((value == Fp_info :: quiet_NaN ())) = 거짓 성공
w = inf, ((value == Fp_info :: quiet_NaN ())) = 거짓 성공

v = nan, ((ilogb (value) == ((int) 0x80000000))) = 진정한 성공
u = 3.14, ((ilogb (value) == ((int) 0x80000000))) = 거짓 성공
w = inf, ((ilogb (value) == ((int) 0x80000000))) = 거짓 성공

v = nan, (isun order (1.2345, value)) = 진정한 성공
u = 3.14, (isun order (1.2345, value)) = 거짓 성공
w = inf, (isun order (1.2345, value)) = 거짓 성공

v = nan, (is_ieee754_nan (value)) = 진정한 성공
u = 3.14, (is_ieee754_nan (value)) = 거짓 성공
w = inf, (is_ieee754_nan (value)) = 거짓 성공

[C : \ my \ 포럼 \ so \ 282 (NaN 감지)]
> g ++ foo.cpp -ffast-math && a
컴파일러, IEEE 754 = 클레임

v = nan, (std :: isnan (value)) = 거짓 실패
u = 3.14, (std :: isnan (value)) = 거짓 성공
w = inf, (std :: isnan (value)) = 거짓 성공

v = nan, ((fpclassify (value) == 0x0100)) = 거짓 실패
u = 3.14, ((fpclassify (value) == 0x0100)) = 거짓 성공
w = inf, ((fpclassify (value) == 0x0100)) = 거짓 성공

v = nan, ((value! = value)) = 거짓 실패
u = 3.14, ((value! = value)) = 거짓 성공
w = inf, ((value! = value)) = 거짓 성공

v = nan, ((value == Fp_info :: quiet_NaN ())) = 진정한 성공
u = 3.14, ((값 == Fp_info :: quiet_NaN ())) = true 실패
w = inf, ((값 == Fp_info :: quiet_NaN ())) = true 실패

v = nan, ((ilogb (value) == ((int) 0x80000000))) = 진정한 성공
u = 3.14, ((ilogb (value) == ((int) 0x80000000))) = 거짓 성공
w = inf, ((ilogb (value) == ((int) 0x80000000))) = 거짓 성공

v = nan, (isun order (1.2345, value)) = 거짓 실패
u = 3.14, (isun order (1.2345, value)) = 거짓 성공
w = inf, (isun order (1.2345, value)) = 거짓 성공

v = nan, (is_ieee754_nan (value)) = 진정한 성공
u = 3.14, (is_ieee754_nan (value)) = 거짓 성공
w = inf, (is_ieee754_nan (value)) = 거짓 성공

[C : \ my \ 포럼 \ so \ 282 (NaN 감지)]
> _

Visual C ++를 사용한 결과 :

[C : \ my \ 포럼 \ so \ 282 (NaN 감지)]
> cl / nologo- 2> & 1 | "++"찾기
x86 용 Microsoft (R) C / C ++ 최적화 컴파일러 버전 19.00.23725

[C : \ my \ 포럼 \ so \ 282 (NaN 감지)]
> cl foo.cpp / 2 월 && b
foo.cpp
컴파일러, IEEE 754 = 클레임

v = nan, (std :: isnan (value)) = true 성공
u = 3.14, (std :: isnan (value)) = 거짓 성공
w = inf, (std :: isnan (value)) = 거짓 성공

v = nan, ((fpclassify (value) == 2)) = 진정한 성공
u = 3.14, ((fpclassify (value) == 2)) = 거짓 성공
w = inf, ((fpclassify (value) == 2)) = 거짓 성공

v = nan, ((value! = value)) = true 성공
u = 3.14, ((value! = value)) = 거짓 성공
w = inf, ((value! = value)) = 거짓 성공

v = nan, ((value == Fp_info :: quiet_NaN ())) = 거짓 FAILED
u = 3.14, ((value == Fp_info :: quiet_NaN ())) = 거짓 성공
w = inf, ((value == Fp_info :: quiet_NaN ())) = 거짓 성공

v = nan, ((ilogb (value) == 0x7fffffff)) = 진정한 성공
u = 3.14, ((ilogb (value) == 0x7fffffff)) = 거짓 성공
w = inf, ((ilogb (value) == 0x7fffffff)) = true 실패

v = nan, (isun order (1.2345, value)) = 진정한 성공
u = 3.14, (isun order (1.2345, value)) = 거짓 성공
w = inf, (isun order (1.2345, value)) = 거짓 성공

v = nan, (is_ieee754_nan (value)) = 진정한 성공
u = 3.14, (is_ieee754_nan (value)) = 거짓 성공
w = inf, (is_ieee754_nan (value)) = 거짓 성공

[C : \ my \ 포럼 \ so \ 282 (NaN 감지)]
> cl foo.cpp / Feb / fp : 빠른 && b
foo.cpp
컴파일러, IEEE 754 = 클레임

v = nan, (std :: isnan (value)) = true 성공
u = 3.14, (std :: isnan (value)) = 거짓 성공
w = inf, (std :: isnan (value)) = 거짓 성공

v = nan, ((fpclassify (value) == 2)) = 진정한 성공
u = 3.14, ((fpclassify (value) == 2)) = 거짓 성공
w = inf, ((fpclassify (value) == 2)) = 거짓 성공

v = nan, ((value! = value)) = true 성공
u = 3.14, ((value! = value)) = 거짓 성공
w = inf, ((value! = value)) = 거짓 성공

v = nan, ((value == Fp_info :: quiet_NaN ())) = 거짓 FAILED
u = 3.14, ((value == Fp_info :: quiet_NaN ())) = 거짓 성공
w = inf, ((value == Fp_info :: quiet_NaN ())) = 거짓 성공

v = nan, ((ilogb (value) == 0x7fffffff)) = 진정한 성공
u = 3.14, ((ilogb (value) == 0x7fffffff)) = 거짓 성공
w = inf, ((ilogb (value) == 0x7fffffff)) = true 실패

v = nan, (isun order (1.2345, value)) = 진정한 성공
u = 3.14, (isun order (1.2345, value)) = 거짓 성공
w = inf, (isun order (1.2345, value)) = 거짓 성공

v = nan, (is_ieee754_nan (value)) = 진정한 성공
u = 3.14, (is_ieee754_nan (value)) = 거짓 성공
w = inf, (is_ieee754_nan (value)) = 거짓 성공

[C : \ my \ 포럼 \ so \ 282 (NaN 감지)]
> _

위의 결과를 종합하면 is_ieee754_nan이 테스트 프로그램에 정의 된 함수를 사용하여 비트 수준 표현의 직접 테스트 만 g ++ 및 Visual C ++ 모두에서 안정적으로 작동했습니다.


부록 :
위의 내용을 게시 한 후 여기 에 또 다른 답변으로 언급 된 NaN을 테스트 할 수있는 또 다른 가능성이 있음을 알게되었습니다 ((value < 0) == (value >= 0)). Visual C ++에서는 잘 작동하지만 g ++의 -ffast-math옵션으로는 실패했습니다 . 직접 비트 패턴 테스트 만 안정적으로 작동합니다.


7
inline bool IsNan(float f)
{
    const uint32 u = *(uint32*)&f;
    return (u&0x7F800000) == 0x7F800000 && (u&0x7FFFFF);    // Both NaN and qNan.
}

inline bool IsNan(double d)
{
    const uint64 u = *(uint64*)&d;
    return (u&0x7FF0000000000000ULL) == 0x7FF0000000000000ULL && (u&0xFFFFFFFFFFFFFULL);
}

이것은 sizeof(int)4이고 sizeof(long long)8 이면 작동합니다 .

런타임 중에는 캐스팅에 불과하지만 시간이 걸리지 않습니다. 평등을 확인하기 위해 비교 플래그 구성 만 변경합니다.


또한 IEEE 754 표현으로 제한됩니다.
건배와 hth. -Alf

이 캐스트는 g ++의 엄격한 앨리어싱 규칙을 위반하며 컴파일러는 공식 UB를 감지 할 때 Unmentionable Things ™를 수행하는 것으로 알려져 있습니다. 효율적인 캐스트 대신 g ++을 사용 memcpy하면 바이트 배열을 통해을 사용해야합니다. 내 # 2 답변의 코드 .
건배와 hth. -Alf

4

사용되는 NaN에 대한 특정 IEEE 표현에 의존하지 않는 가능한 솔루션은 다음과 같습니다.

template<class T>
bool isnan( T f ) {
    T _nan =  (T)0.0/(T)0.0;
    return 0 == memcmp( (void*)&f, (void*)&_nan, sizeof(T) );
}

단 정밀도 부동 소수점은 NaN에 대해 8 백만 건의 합법적이고 다른 비트 표현을 가지므로 더 많은 비교를 추가해야합니다. :)
Steve Hollasch 1

4

Nax에 대해 (x! = x)가 항상 보장되는 것은 아니라는 점을 고려하여 (-ffast-math 옵션을 사용하는 경우와 같이) 다음을 사용했습니다.

#define IS_NAN(x) (((x) < 0) == ((x) >= 0))

숫자는 <0과> = 0 일 수 없으므로 실제로이 검사는 숫자가 0보다 작거나 0보다 크지 않은 경우에만 통과합니다. 기본적으로 전혀 숫자가 없거나 NaN입니다.

원하는 경우 이것을 사용할 수도 있습니다.

#define IS_NAN(x) (!((x)<0) && !((x)>=0)

그래도 이것이 -ffast-math의 영향을 받는지 확실하지 않으므로 마일리지가 다를 수 있습니다.


이것은 실제로 같은 방식 f != f으로 결함이 있습니다. 나는 llvm이 거의 동일한 코드 조각을 최적화하는 것을 보았습니다. 옵티마이 저는 첫 번째 비교에 대한 정보를 전파하고 첫 번째 비교가 두 번째 비교가 사실이 아님을 알 수 있습니다. (컴파일러 f != f가 IEEE 규칙을 엄격하게 준수하는 경우 훨씬 간단합니다)
Markus

g ++의 -ffast-math옵션으로 는 작동하지 않습니다 . Visual C ++에서 작동합니다. ( stackoverflow.com/a/42138465/464581 )을 참조하십시오 .
건배와 hth. -Alf

3

나에게 해결책은 명시 적으로 인라인하여 충분히 빠를 수있는 매크로 일 수 있습니다. 모든 플로트 유형에도 작동합니다. 값이 같지 않은 유일한 경우는 값이 숫자가 아니라는 사실에 근거합니다.

#ifndef isnan
  #define isnan(a) (a != a)
#endif

이것은이 질문에 가장 적합한 답변 중 하나입니다! 공유해 주셔서 감사합니다.
Henri Menke

2
다른 답변은 -ffast-math 옵션 세트로 실패 할 수 있음을 나타냅니다.
Technophile

3

이것은 작동합니다 :

#include <iostream>
#include <math.h>
using namespace std;

int main ()
{
  char ch='a';
  double val = nan(&ch);
  if(isnan(val))
     cout << "isnan" << endl;

  return 0;
}

출력 : isnan


1

정말 진정한 크로스 플랫폼 접근 방식은 공용체를 사용하고 이중의 비트 패턴을 테스트하여 NaN을 확인하는 것 같습니다.

나는이 솔루션을 철저히 테스트하지 않았으며 비트 패턴을 사용하는보다 효율적인 방법이있을 수 있지만 작동해야한다고 생각합니다.

#include <stdint.h>
#include <stdio.h>

union NaN
{
    uint64_t bits;
    double num;
};

int main()
{
    //Test if a double is NaN
    double d = 0.0 / 0.0;
    union NaN n;
    n.num = d;
    if((n.bits | 0x800FFFFFFFFFFFFF) == 0xFFFFFFFFFFFFFFFF)
    {
        printf("NaN: %f", d);
    }

    return 0;
}

"가장 최근에 작성되지 않은 통합 멤버에서 읽는 것은 정의되지 않은 동작입니다." 따라서 union두 유형 사이에 유형 펀칭을 사용하면 원하는대로 작동하지 않을 수 있습니다 (: sad_panda :). 올바른 (실제로 원하는만큼 이식성이 좋지는 않지만) 방법은 통합을 완전히 피하고 double다른 uint64_t변수 로 memcpy 를 수행 한 다음 해당 도우미 변수를 사용하여 테스트를 수행하는 것입니다.
Eljay

0

x86-64에서는 -ffast-math컴파일러 옵션에 관계없이 NaN 및 무한대를 확인하는 매우 빠른 방법을 사용할 수 있습니다 . ( f != f, std::isnan, std::isinf항상 양보 false-ffast-math).


NaN, 무한대 및 유한 수에 대한 테스트는 최대 지수를 확인하여 쉽게 수행 할 수 있습니다. 무한대는 가수가 0 인 최대 지수이고, NaN은 최대 지수이며 0이 아닌 가수입니다. 지수는 최상위 부호 비트 다음에 다음 비트에 저장되므로 부호 비트를 제거하고 지수를 최상위 비트로 만들기 위해 시프트를 왼쪽으로 할 수 있으므로 마스킹 ( operator&)이 필요 하지 않습니다.

static inline uint64_t load_ieee754_rep(double a) {
    uint64_t r;
    static_assert(sizeof r == sizeof a, "Unexpected sizes.");
    std::memcpy(&r, &a, sizeof a); // Generates movq instruction.
    return r;
}

static inline uint32_t load_ieee754_rep(float a) {
    uint32_t r;
    static_assert(sizeof r == sizeof a, "Unexpected sizes.");
    std::memcpy(&r, &a, sizeof a); // Generates movd instruction.
    return r;
}

constexpr uint64_t inf_double_shl1 = UINT64_C(0xffe0000000000000);
constexpr uint32_t inf_float_shl1 = UINT32_C(0xff000000);

// The shift left removes the sign bit. The exponent moves into the topmost bits,
// so that plain unsigned comparison is enough.
static inline bool isnan2(double a)    { return load_ieee754_rep(a) << 1  > inf_double_shl1; }
static inline bool isinf2(double a)    { return load_ieee754_rep(a) << 1 == inf_double_shl1; }
static inline bool isfinite2(double a) { return load_ieee754_rep(a) << 1  < inf_double_shl1; }
static inline bool isnan2(float a)     { return load_ieee754_rep(a) << 1  > inf_float_shl1; }
static inline bool isinf2(float a)     { return load_ieee754_rep(a) << 1 == inf_float_shl1; }
static inline bool isfinite2(float a)  { return load_ieee754_rep(a) << 1  < inf_float_shl1; }

std의 버전 isinfisfinite로드 2 개 double/float에서 상수 .data세그먼트와 최악의 시나리오에 그들은 2 데이터 캐시 미스가 발생할 수 있습니다. 위의 버전은 데이터를로드하지 않습니다, inf_double_shl1그리고 inf_float_shl1상수는 조립 설명서에 즉시 피연산자로 인코딩 된 얻을.


더 빠른 isnan2조립 지침은 두 가지입니다.

bool isnan2(double a) {
    bool r;
    asm(".intel_syntax noprefix"
        "\n\t ucomisd %1, %1"
        "\n\t setp %b0"
        "\n\t .att_syntax prefix"
        : "=g" (r)
        : "x" (a)
        : "cc"
        );
    return r;
}

ucomisd인수가 NaN이면 명령어가 패리티 플래그를 설정 한다는 사실을 사용합니다. 이것은 옵션이 지정 std::isnan되지 않은 경우 작동 하는 방식 -ffast-math입니다.


-1

IEEE 표준에 따르면 지수가 모두 1이고 가수가 0이 아닌 경우 숫자는입니다 NaN. Double은 1부호 비트, 11지수 비트 및 52가수 비트입니다. 조금 확인하십시오.


-3

위의 주석에서 a == a는 g ++ 및 다른 컴파일러에서 작동하지 않지만이 트릭은 작동해야합니다. 효율적이지 않을 수도 있지만 여전히 방법입니다.

bool IsNan(float a)
{
    char s[4];
    sprintf(s, "%.3f", a);
    if (s[0]=='n') return true;
    else return false;
}

기본적으로 g ++에서 (다른 사람들에 대해서는 잘 모르겠습니다) printf는 변수가 유효한 정수 / 부동 소수점이 아닌 경우 % d 또는 % .f 형식으로 'nan'을 인쇄합니다. 따라서이 코드는 문자열의 첫 번째 문자가 'n'인지 확인합니다 ( "nan"과 같이).


2
a = 234324.0f이면 버퍼 오버플로가 발생하지 않습니까?
Mazyod

예, 또는 340282346638528859811704183484516925440.000a = 인 경우 FLT_MAX. 그는을 사용해야하는데 char s[7]; sprintf(s, "%.0g", a);,이 경우 6 chrs a=-FLT_MAX, 또는-3e+38
bobobobo

-3

이것은 무한대와 Visual Studio에서 NaN이 이중 한계 내에 있는지 확인하여 감지합니다.

//#include <float.h>
double x, y = -1.1; x = sqrt(y);
if (x >= DBL_MIN && x <= DBL_MAX )
    cout << "DETECTOR-2 of errors FAILS" << endl;
else
    cout << "DETECTOR-2 of errors OK" << endl;

의 정의를 확인 FLT_MIN, DBL_MIN그리고 LDBL_MIN더 신중하게. 이들은 각 유형에 대해 가장 작은 정규화 된 값 으로 정의됩니다 . 예를 들어, 단 정밀도는 0보다 크고 적고 FLT_MIN(NaN이 아닌) 8 백만 개 이상의 적법한 denorm 값을 가지고 있습니다 .
Steve Hollasch 1
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.