IEEE754要求NaN必须是无序的;当一个或两个操作数均为NaN时,小于,大于,等于等都应返回false。
下面的示例在所有优化级别上使用g++进行编译时,以及在不使用优化参数或不使用/Od,/fp:fast的任何组合的情况下使用VC++的CL.exe(32位版本15.00.30729.01)进行编译时,将产生预期的正确F F F F F T
。 ,/arch:SSE。
但是,当使用/O1或/O2(以及任何/没有其他优化参数)进行编译时,即使指定了/Op,也会生成T T F F F T
。
CL.exe的64位版本会产生许多变化-T T F F F T
,T T T F F T
和T T T F F F
等-取决于优化级别以及是否指定了/fp:fast,但与32位版本一样,仅在以下情况下才可能出现兼容行为:禁用所有优化。
我在犯一些明显的错误吗?有什么方法可以使编译器在不牺牲所有其他优化的情况下符合此处的标准?
#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的问题。
最佳答案
因此,总而言之,存在许多单独的问题:
/fp:fast
解决了我可以使用的所有32位和64位编译器版本的问题/fp:fast
关于c++ - VC++优化是否打破了与NaN的比较?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/15786606/