[c] C에서 nan과 inf를 사용하는 방법?

오류가있는 경우 nan 또는 inf를 반환 할 수있는 숫자 메서드가 있으며, 테스트 목적으로 상황이 올바르게 처리되고 있는지 확인하기 위해 일시적으로 nan 또는 inf를 반환하도록 강제하고 싶습니다. C에서 nan 및 inf 값을 생성 하는 신뢰할 수 있고 컴파일러 독립적 인 방법이 있습니까?

약 10 분 동안 인터넷 검색을 한 후 컴파일러 종속 솔루션 만 찾을 수있었습니다.



답변

구현에 다음이 있는지 테스트 할 수 있습니다.

#include <math.h>
#ifdef NAN
/* NAN is supported */
#endif
#ifdef INFINITY
/* INFINITY is supported */
#endif

의 존재는 INFINITYC99 (또는 적어도 최신 초안)에 의해 보장되며 “사용 가능한 경우 양수 또는 부호없는 무한대를 나타내는 float 유형의 상수 표현식으로 확장됩니다. 그렇지 않으면 번역시 오버플로되는 float 유형의 양의 상수로 확장됩니다.”

NAN 정의되거나 정의되지 않을 수 있으며 “구현이 float 유형에 대해 조용한 NaN을 지원하는 경우에만 정의됩니다. 이는 조용한 NaN을 나타내는 float 유형의 상수 표현식으로 확장됩니다.”

부동 소수점 값을 비교하는 경우 다음을 수행하십시오.

a = NAN;

그렇다하더라도,

a == NAN;

거짓입니다. NaN을 확인하는 한 가지 방법은 다음과 같습니다.

#include <math.h>
if (isnan(a)) { ... }

다음 a != a을 수행 할 수도 있습니다 a. NaN 인지 테스트합니다 .

도있다 isfinite(), isinf(), isnormal(), 및 signbit()매크로에 math.hC99한다.

C99에는 다음과 같은 nan기능 도 있습니다 .

#include <math.h>
double nan(const char *tagp);
float nanf(const char *tagp);
long double nanl(const char *tagp);

(참조 : n1256).

문서 INFINITY
문서 NAN


답변

C (또는 C ++) 표준이 부동 소수점 수학 유형이 NAN 또는 INF를 지원해야한다고 말하지 않기 때문에이를 수행하는 컴파일러 독립적 인 방법은 없습니다.

편집 : 방금 C ++ 표준의 문구를 확인한 결과 다음 함수 (템플릿 클래스 numeric_limits의 구성원)가 다음과 같이 표시됩니다.

quiet_NaN()
signalling_NaN()

“사용 가능한 경우”NAN 표현을 반환합니다. “가능한 경우”가 의미하는 바를 확장하지 않고 “구현의 FP 담당자가 지원하는 경우”와 같은 것으로 추정됩니다. 마찬가지로 기능이 있습니다.

infinity()

“사용 가능한 경우”양의 INF 담당자를 반환합니다.

이것들은 모두 <limits>헤더에 정의되어 있습니다. C 표준에도 비슷한 것이 있다고 생각하지만 (아마도 “사용 가능한 경우”) 현재 C99 표준의 사본이 없습니다.


답변

이것은 floatdouble:

double NAN = 0.0/0.0;
double POS_INF = 1.0 /0.0;
double NEG_INF = -1.0/0.0;

편집 : 누군가 이미 말했듯이 이전 IEEE 표준은 이러한 값이 함정을 유발해야한다고 말했습니다. 그러나 새 컴파일러는 트랩이 오류 처리를 방해하기 때문에 거의 항상 트랩을 끄고 주어진 값을 반환합니다.


답변

컴파일러 독립적 인 방법이지만 프로세서 독립적 인 방법은 아닙니다.

int inf = 0x7F800000;
return *(float*)&inf;

int nan = 0x7F800001;
return *(float*)&nan;

이것은 IEEE 754 부동 소수점 형식을 사용하는 모든 프로세서에서 작동합니다 (x86이 수행함).

업데이트 : 테스트 및 업데이트되었습니다.


답변

double a_nan = strtod("NaN", NULL);
double a_inf = strtod("Inf", NULL);


답변

<inf.h>

/* IEEE positive infinity.  */

#if __GNUC_PREREQ(3,3)
# define INFINITY   (__builtin_inff())
#else
# define INFINITY   HUGE_VALF
#endif

<bits/nan.h>
#ifndef _MATH_H
# error "Never use <bits/nan.h> directly; include <math.h> instead."
#endif


/* IEEE Not A Number.  */

#if __GNUC_PREREQ(3,3)

# define NAN    (__builtin_nanf (""))

#elif defined __GNUC__

# define NAN \
  (__extension__                                  \
   ((union { unsigned __l __attribute__ ((__mode__ (__SI__))); float __d; })  \
    { __l: 0x7fc00000UL }).__d)

#else

# include <endian.h>

# if __BYTE_ORDER == __BIG_ENDIAN
#  define __nan_bytes       { 0x7f, 0xc0, 0, 0 }
# endif
# if __BYTE_ORDER == __LITTLE_ENDIAN
#  define __nan_bytes       { 0, 0, 0xc0, 0x7f }
# endif

static union { unsigned char __c[4]; float __d; } __nan_union
    __attribute_used__ = { __nan_bytes };
# define NAN    (__nan_union.__d)

#endif  /* GCC.  */


답변

나는 또한 이것이 컴파일 시간 상수가 아니라는 것에 놀랐습니다. 그러나 이러한 잘못된 결과를 반환하는 명령을 실행하여 이러한 값을 쉽게 만들 수 있다고 가정합니다. 0으로 나누면 log는 0이고 tan은 90입니다.