エラーが発生した場合にnanまたはinfを返すことができる数値メソッドがあります。テストを目的として、状況を正しく処理するために一時的にnanまたはinfを強制的に返したいと思います。 Cでnanとinfの値を作成するための信頼できるcompiler-independentの方法はありますか?
約10分間グーグルで調べた後、コンパイラー依存のソリューションしか見つけることができませんでした。
実装にそれがあるかどうかをテストできます。
_#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)。
C(またはC++)標準も浮動小数点演算タイプがNANまたはINFをサポートする必要があると言っていないため、これを行うコンパイラーに依存しない方法はありません。
編集: C++標準の文言を確認したところ、これらの関数(テンプレートクラスnumeric_limitsのメンバー)が次のように記述されています。
quiet_NaN()
signalling_NaN()
「利用可能な場合」NAN表現を返します。 「利用可能な場合」の意味は拡張されませんが、おそらく「実装のFP repがサポートする場合」のようなものです。同様に、関数があります。
infinity()
正のINF rep "if available"を返します。
これらは両方とも<limits>
ヘッダーで定義されています-C標準には似たものがあると思いますが(おそらく「使用可能な場合」)、現在のC99標準のコピーはありません。
これはfloat
とdouble
の両方で機能します:
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. */
私は通常使用します
#define INFINITY (1e999)
または
const double INFINITY = 1e999
これは、少なくともIEEE 754コンテキストで機能します。これは、表現可能な最大のdouble値がおおよそ1e308
であるためです。 1e309
は1e99999
と同様に機能しますが、スリーナインで十分で記憶に残ります。これは、ダブルリテラル(#define
の場合)または実際のInf
値であるため、128ビット(「ロングダブル」)浮動小数点を使用している場合でも無限に残ります。
また、これらがコンパイル時定数ではないことにも驚いています。しかし、このような無効な結果を返す命令を実行するだけで、これらの値を簡単に作成できると思います。 0、0のログ、90の日焼け、そのようなことで除算します。