33

C ++でNaNを使用する最良の方法は何ですか?

std::numeric_limits<double>::quiet_NaN()とを見つけましstd::numeric_limits<double>::signaling_NaN()た。signaling_NaN次のように、初期化されていない変数を表すために使用したいと思います。

double diameter = std::numeric_limits<double>::signaling_NaN();

ただし、これは割り当て時に通知されます (例外が発生します)。割り当てではなく、使用時に例外を発生させたい。

signaling_NaN割り当て時に例外を発生させずに使用する方法はありますか? signaling_NaN使用時に浮動小数点例外が発生する、移植可能な優れた代替手段はありますか?

4

6 に答える 6

11

これをもう少し調べたところsignaling_NaN、提供されているのは役に立たないようです。浮動小数点例外が有効になっている場合、それを呼び出すと、シグナル NaN の処理としてカウントされるため、すぐに例外が発生します。浮動小数点例外が無効になっている場合、シグナリング NaN を処理すると、自動的にそれがクワイエット NaN に降格されるため、signaling_NaNどちらの方法でも機能しません。

Menkboy のコードは機能しますが、シグナリング NaN を使用しようとすると、他の問題が発生します: 浮動小数点例外を有効または無効にする移植可能な方法はありません (ここここでほのめかされているように)。それらを無効にします(ここで説明されているように)。

したがって、モッティのソリューションは本当に最良の選択のようです。

于 2008-11-11T18:32:35.827 に答える
9

シグナリング NAN が意味することは、CPU がそれに遭遇したときにシグナルが発生することです (したがって、名前が付けられています)。初期化されていない変数を検出したい場合、コンパイラで警告レベルを上げると、通常、初期化されていない値を使用するすべてのパスが検出されます。値が初期化されているかどうかを示すブール値を格納するラッパー クラスを使用できない場合:

template <class T>
class initialized {
    T t;
    bool is_initialized;
public:
    initialized() : t(T()), is_initialized(false) { }
    initialized(const T& tt) : t(tt), is_initialized(true) { }
    T& operator=(const T& tt) { t = tt; is_initialized = true; return t; }
    operator T&() {
         if (!is_initialized)
             throw std::exception("uninitialized");
         return t; 
   }
};
于 2008-10-25T20:02:27.903 に答える
3

ええと、静かな NaN とシグナリング NaN の両方の定義を調べてみると、実際には違いがわかりません。

これらの関数で使用されているコードを自分で使用することもできます。おそらく、その方法で例外を防ぐことができますが、これら 2 つの関数で例外が見られない場合は、他の何かに関連している可能性があると思います。

NaN を直接割り当てたい場合:

double value = _Nan._Double;
于 2008-10-25T19:57:05.107 に答える
3

このようなもので例外をトリガーすることなく、シグナリング NaN を変数に書き込むことができます (注意: 未テスト)

void set_snan( double &d )
{
    long long *bits = (long long *)&d;
    *bits = 0x7ff0000080000001LL;
}

ほとんどの場所で動作しますが、100% 移植できるわけではありません。

于 2008-10-24T22:35:59.523 に答える
3

簡単な答え: ヘッダー ファイルで次のようなことを行い、それを他の場所で使用します。

#define NegativeNaN log(-1)

それらに対して何らかの操作を行いたい場合は、拡張ラッパー関数exp()などextended_exp()を記述してください。

于 2012-11-05T15:49:34.910 に答える
0

C++ 実装には、特定の浮動小数点例外をテストしてクリアするために浮動小数点環境にアクセスするための API が含まれている場合があります。詳細については、関連する質問に対する私の回答を参照してください。

于 2008-10-24T22:42:48.773 に答える