web-dev-qa-db-ja.com

Cでnanとinfを使用する方法は?

エラーが発生した場合にnanまたはinfを返すことができる数値メソッドがあります。テストを目的として、状況を正しく処理するために一時的にnanまたはinfを強制的に返したいと思います。 Cでnanとinfの値を作成するための信頼できるcompiler-independentの方法はありますか?

約10分間グーグルで調べた後、コンパイラー依存のソリューションしか見つけることができませんでした。

83
Graphics Noob

実装にそれがあるかどうかをテストできます。

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

INFINITYの存在はC99(または少なくとも最新のドラフト)によって保証されており、「利用可能な場合、正または符号なしの無限大を表すfloat型の定数式に展開されます。翻訳時にオーバーフローします。」

NANは定義される場合とされない場合があり、「実装がfloat型のquiet NaNをサポートする場合にのみ定義されます。quietNaNを表すfloat型の定数式に展開されます。」

浮動小数点値を比較する場合は、次のことに注意してください。

_a = NAN;
_

その時でさえ、

_a == NAN;
_

偽です。 NaNを確認する1つの方法は次のとおりです。

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

aがNaNかどうかをテストする_a != a_も実行できます。

C99の_math.h_には、isfinite()isinf()isnormal()、およびsignbit()マクロもあります。

C99にはnan関数もあります。

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

(参照:n1256)。

ドキュメントINFINITYドキュメントNAN

77
Alok Singhal

C(またはC++)標準も浮動小数点演算タイプがNANまたはINFをサポートする必要があると言っていないため、これを行うコンパイラーに依存しない方法はありません。

編集: C++標準の文言を確認したところ、これらの関数(テンプレートクラスnumeric_limitsのメンバー)が次のように記述されています。

quiet_NaN() 
signalling_NaN()

「利用可能な場合」NAN表現を返します。 「利用可能な場合」の意味は拡張されませんが、おそらく「実装のFP repがサポートする場合」のようなものです。同様に、関数があります。

infinity() 

正のINF rep "if available"を返します。

これらは両方とも<limits>ヘッダーで定義されています-C標準には似たものがあると思いますが(おそらく「使用可能な場合」)、現在のC99標準のコピーはありません。

34
anon

これはfloatdoubleの両方で機能します:

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

編集:誰かがすでに言ったように、古いIEEE規格は、そのような値はトラップを発生させるべきだと述べました。ただし、トラップはエラー処理を妨げるため、新しいコンパイラはほとんど常にトラップをオフにして、指定された値を返します。

20
Thorsten S.

コンパイラに依存しない方法ですが、プロセッサに依存しない方法でこれらを取得します:

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

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

これは、IEEE 754浮動小数点フォーマット(x86が使用)を使用するプロセッサーで動作するはずです。

更新:テストおよび更新。

19
Aaron
double a_nan = strtod("NaN", NULL);
double a_inf = strtod("Inf", NULL);
12
J.Kraftcheck
<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.  */
3
4pie0

私は通常使用します

#define INFINITY (1e999)

または

const double INFINITY = 1e999

これは、少なくともIEEE 754コンテキストで機能します。これは、表現可能な最大のdouble値がおおよそ1e308であるためです。 1e3091e99999と同様に機能しますが、スリーナインで十分で記憶に残ります。これは、ダブルリテラル(#defineの場合)または実際のInf値であるため、128ビット(「ロングダブル」)浮動小数点を使用している場合でも無限に残ります。

0
Douglas Bagnall

また、これらがコンパイル時定数ではないことにも驚いています。しかし、このような無効な結果を返す命令を実行するだけで、これらの値を簡単に作成できると思います。 0、0のログ、90の日焼け、そのようなことで除算します。

0
Carl Smotricz