IEEE754 では、NaN が順序付けされていない必要があります。一方または両方のオペランドが NaN の場合、より小さい、より大きい、等しいなどはすべて false を返す必要があります。
以下のサンプルはF F F F F T
、すべての最適化レベルで g++ を使用してコンパイルした場合、および最適化引数を指定せずに、または /Od、/fp:fast、 /arch:SSE.
ただし、/O1 または /O2 (およびその他の最適化引数を使用する/使用しない) を使用してコンパイルすると、T T F F F T
/Op も指定した場合でも結果が得られます。
CL.exe の 64 ビット バージョンは、最適化レベルと /fp:fast が指定されているかどうかに応じて、多くのバリエーション( 、T T F F F T
など)を生成しますが、32 ビット バージョンと同様に、準拠した動作はすべての最適化が無効になっている場合にのみ可能であるようです。 .T T T F F T
T T T F F F
私は明らかな間違いを犯していますか?他のすべての最適化を犠牲にすることなく、ここでコンパイラを標準に準拠させる方法はありますか?
#include <limits>
#include <stdio.h>
int main( int argc, char const ** argv )
{
float test = std::numeric_limits<float>::quiet_NaN();
printf( "%c %c %c %c %c %c\n",
(test < test) ? 'T' : 'F',
(test <= test) ? 'T' : 'F',
(test == test) ? 'T' : 'F',
(test > test) ? 'T' : 'F',
(test >= test) ? 'T' : 'F',
(test != test) ? 'T' : 'F'
);
return 0;
}
build.cmd
問題を再現する例:
set "PATH=c:\program files (x86)\Microsoft Visual Studio 9.0\VC\bin\amd64;c:\program files (x86)\Microsoft Visual Studio 9.0\Common7;c:\program files (x86)\Microsoft Visual Studio 9.0\Common7\IDE"
set "LIB=c:\program files (x86)\microsoft visual studio 9.0\vc\lib\x64;c:\program files\Microsoft SDKs\Windows\v6.0A\Lib\x64"
cl test.cpp /fp:fast /Od /c /I "c:\program files (x86)\microsoft visual studio 9.0\vc\include"
link "/LIBPATH:C:/Program Files (x86)/Microsoft Visual Studio 9.0/vc/lib/amd64" "/LIBPATH:C:\Program Files\Microsoft SDKs\Windows\v6.0A\/Lib/x64" /DEBUG /IGNORE:4199 /IGNORE:4221 /MACHINE:X64 /SUBSYSTEM:CONSOLE test.obj
test
編集
記録のために、最初に使用された質問で与えられた例
inline float QNaN()
{
static int const QNaNValue = 0x7fc00000;
return *(reinterpret_cast<float const*>(&QNaNValue));
}
NaN を生成します。多くのコメントと回答が指摘しているように、これは未定義の動作であり、実際に std::numeric_limits::quiet_NaN() に置き換えると、32 ビット CL.exe の一部のバージョンの問題が修正されました。