質問
いくつかのテストケースを書いている間、および一部のテストではNANの結果をチェックします。
使ってみました std::isnan
しかし、アサートは失敗します:
Assertion `std::isnan(x)' failed.
の値を印刷した後 x
, 、それはネガティブナンであることが判明しました(-nan
)私の場合は完全に受け入れられます。
それを使用しようとした後 NaN != NaN
そして使用します assert(x == x)
, 、コンパイラは私に「好意」を与え、アサートを最適化します。
私自身を作っています isNaN
機能も最適化されています。
NANの平等の両方を確認するにはどうすればよいですか と - ナン?
解決
これは恥ずかしいです。
コンパイラ(この場合はGCC)が比較を最適化した理由と isnan
戻ってきた false
私のチームの誰かがオンになっていたからです -ffast-math
.
ドキュメントから:
-ffast-math Sets -fno-math-errno, -funsafe-math-optimizations, -fno-trapping-math, -ffinite-math-only, -fno-rounding-math, -fno-signaling-nans and fcx-limited-range. This option causes the preprocessor macro __FAST_MATH__ to be defined. This option should never be turned on by any -O option since it can result in incorrect output for programs which depend on an exact implementation of IEEE or ISO rules/specifications for math functions.
エンディング文に注意してください - -ffast-math
安全ではありません。
他のヒント
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
これはあなたの図書館の実装のバグのように見えます isnan()
私に。 Snow LeopardのGCC 4.2.1ではここで正常に動作します。しかし、これを試してみるのはどうですか?
std::isnan(std::abs(yourNanVariable));
明らかに、私はそれをテストすることはできません std::isnan(-NaN)
は true
私のシステムで。
編集: : と -ffast-math
, 、それに関係なく -O
スイッチ、Snow LeopardのGCC 4.2.1はそれを考えています NAN == NAN
は true
, 、 そのまま NAN == -NAN
. 。これは、潜在的にコードを壊滅的に破壊する可能性があります。私は離れることをアドバイスします -ffast-math
または、少なくともビルドを使用して使用しないで同一の結果をテストする...
C99 ISNAN()があります。
実装では正しく機能しない場合(どちらですか?)、Long to Longに再解釈してIEEE Bit Magicを実行することで、独自の実装を実装できます。
数のビットを確認できます。 IEEE 754は、NANのマスクを定義しています。
- シグナル伝達NANは、x'7F80 0001 'とX'7FBF FFFF'またはX'FF80 0001 'およびX'FFBF FFFF'の間のビットパターンで表されます。
- 静かなナンは、x'7fc0 0000 'とx'7fff ffff'またはx'ffc0 0000 'とx'ffff ffff'の間の任意のパターンで表されます。
これはポータブルではないかもしれませんが、PlatfofMについて確信している場合は、受け入れられる可能性があります。もっと: http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=/com.ibm.xlf101l.doc/xlfopg/fpieee.htm
これは、コメントに投稿されたウィキペディアの記事に基づいています。それは完全にテストされていないことに注意してください - それはあなたができることのアイデアをあなたに与えるはずです。
bool reallyIsNan(float x)
{
//Assumes sizeof(float) == sizeof(int)
int intIzedX = *(reinterpret_cast<int *>(&x));
int clearAllNonNanBits = intIzedX & 0x7F800000;
return clearAllNonNanBits == 0x7F800000;
}
編集:Glibcの人たちにバグを提出することを検討する必要があると思います。