31

いくつかのテストケースを書きながら、いくつかのテストは NaN の結果をチェックします。

使用してみstd::isnanましたが、アサートは失敗します:

Assertion `std::isnan(x)' failed.

の値を出力した後、私の場合は完全に受け入れられるx負の NaN ( ) であることがわかりました。-nan

その事実と を使用しようとした後NaN != NaNassert(x == x)コンパイラは私に「好意」を示し、アサートを最適化します。

独自のisNaN関数を作成することも最適化されています。

NaN-NaN の両方が等しいことを確認するにはどうすればよいですか?

4

6 に答える 6

42

これは恥ずかしいです。

コンパイラ (この場合は GCC) が比較を最適化してisnan返さfalseれた理由は、私のチームの誰かが をオンにしたため-ffast-mathです。

ドキュメントから:

-ffast-数学
    -fno-math-errno、-funsafe-math-optimizations、
    -fno-trapping-math、-ffinite-math-only、-fno-rounding-math、-fno-signaling-nans、および fcx-limited-range。

    このオプションにより、プリプロセッサ マクロ __FAST_MATH__ が定義されます。

    数学関数の IEEE または ISO ルール/仕様の正確な実装に依存するプログラムの出力が正しくない可能性があるため、このオプションを -O オプションでオンにしないでください。

末尾の文に注意してください --ffast-mathは安全ではありません。

于 2010-08-29T21:51:04.007 に答える
5

isnan()では、未定義の動作が予想されます-ffast-math

これは、テスト スイートで使用するものです。

#if defined __FAST_MATH__
#   undef isnan
#endif
#if !defined isnan
#   define isnan isnan
#   include <stdint.h>
static inline int isnan(float f)
{
    union { float f; uint32_t x; } u = { f };
    return (u.x << 1) > 0xff000000u;
}
#endif
于 2011-09-17T14:29:47.280 に答える
1

使用できるはずの C99 isnan() があります。

あなたの実装で正しく動作しない場合 (それはどれですか?)、reinterpret_casting を long にし、IEEE ビット マジックを実行することで、独自の実装を行うことができます。

于 2010-08-29T21:26:26.693 に答える
1

これは、ライブラリの実装のバグのように見えますisnan()。ここでは、Snow Leopard の gcc 4.2.1 で問題なく動作します。しかし、これを試してみてはどうでしょうか。

std::isnan(std::abs(yourNanVariable));

明らかに、私のシステム上にstd::isnan(-NaN)あるため、テストできません。true

EDIT : では、スイッチ-ffast-mathに関係なく、 Snow Leopard の gcc 4.2.1はそのまま-Oだと考えます。これにより、コードが壊滅的に壊れる可能性があります。オフにするか、少なくともそれを使用するビルドと使用しないビルドで同じ結果をテストすることをお勧めします...NAN == NANtrueNAN == -NAN-ffast-math

于 2010-08-29T21:52:58.047 に答える
0

数値のビットを確認できます。IEEE 754 は、NaN のマスクを定義しています。

  • シグナリング NaN は、X'7F80 0001' と X'7FBF FFFF' の間、または X'FF80 0001' と X'FFBF FFFF' の間の任意のビット パターンで表されます。
  • quiet NaN は、X'7FC0 0000' と X'7FFF FFFF' の間、または X'FFC0 0000' と X'FFFF FFFF' の間の任意のビット パターンで表されます。

これは移植性がないかもしれませんが、プラットフォームについて確信がある場合は許容できます。詳細: http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=/com.ibm.xlf101l.doc/xlfopg/fpieee.htm

于 2010-08-29T21:30:24.227 に答える
-3

これは、コメントに投稿されたウィキペディアの記事に基づいています。完全にテストされていないことに注意してください。ただし、できることのアイデアが得られるはずです。

bool reallyIsNan(float x)
{
    //Assumes sizeof(float) == sizeof(int)
    int intIzedX = *(reinterpret_cast<int *>(&x));
    int clearAllNonNanBits = intIzedX & 0x7F800000;
    return clearAllNonNanBits == 0x7F800000;
}

編集:しかし、GLibcの人たちにバグを報告することを検討する必要があると本当に思います。

于 2010-08-29T21:30:19.590 に答える