如果任一自变量是NaN,什么会使C/C ++<,< =和==运算符返回true? [英] What would cause the C/C++ <, <=, and == operators to return true if either argument is NaN?

查看:44
本文介绍了如果任一自变量是NaN,什么会使C/C ++<,< =和==运算符返回true?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对IEEE-754浮点比较的规则的理解是,如果!= 中的任何一个或两个参数均为NaN,则除!= 之外的所有比较运算符都将返回false,而!= 运算符将返回true.我可以通过简单的独立测试轻松重现此行为:

(int ii = 0; ii< 4; ++ ii)的

 {浮点a =(ii& 1)!= 0NAN:1.0f;浮点b =(ii& 2)!= 0NAN:2.0f;#define TEST(OP)printf(%4.1f%2s%4.1f =>%s \ n",a,#OP,b,OP b?"true":"false");测试(<)测试(>)测试(< =)测试(> =)测试(==)测试(!=)} 

这会打印出预期的结果:(NaN在MSVC运行时中的格式为 -1.$ )

  1.0<2.0 =>真的1.0>2.0 =>错误的1.0< = 2.0 =>真的1.0> = 2.0 =>错误的1.0 == 2.0 =>错误的1.0!= 2.0 =>真的-1.$<2.0 =>错误的-1.$>2.0 =>错误的-1.$< = 2.0 =>错误的-1.$> = 2.0 =>错误的-1.$ == 2.0 =>错误的-1.$!= 2.0 =>真的1.0以下-1.$ =>错误的1.0>-1.$ =>错误的1.0< = -1.$ =>错误的1.0> = -1.$ =>错误的1.0 == -1.$ =>错误的1.0!= -1.$ =>真的-1.$<-1.$ =>错误的-1.$>-1.$ =>错误的-1.$< = -1.$ =>错误的-1.$> = -1.$ =>错误的-1.$ == -1.$ =>错误的-1.$!= -1.$ =>真的 

但是,当我将这段代码粘贴到应用程序的内部循环的深处(执行所有浮点计算)时,我得到了这些莫名其妙的结果:

  1.0<2.0 =>真的1.0>2.0 =>错误的1.0< = 2.0 =>真的1.0> = 2.0 =>错误的1.0 == 2.0 =>错误的1.0!= 2.0 =>真的-1.$<2.0 =>真的-1.$>2.0 =>错误的-1.$< = 2.0 =>真的-1.$> = 2.0 =>错误的-1.$ == 2.0 =>真的-1.$!= 2.0 =>错误的1.0以下-1.$ =>真的1.0>-1.$ =>错误的1.0< = -1.$ =>真的1.0> = -1.$ =>错误的1.0 == -1.$ =>真的1.0!= -1.$ =>错误的-1.$<-1.$ =>真的-1.$>-1.$ =>错误的-1.$< = -1.$ =>真的-1.$> = -1.$ =>错误的-1.$ == -1.$ =>真的-1.$!= -1.$ =>错误的 

由于某些原因,当两个参数中的任何一个或两个都为时,< < = == 运算符意外返回true.NaN.此外,!= 运算符意外返回false.

这是使用Visual Studio 2010构建的64位代码,在Intel Xeon E5-2650上运行.使用 _mm_getcsr(),我已经确认CSR寄存器在两种情况下都具有相同的值.

还有什么会影响像这样的浮点数学运算的行为?

解决方案

此行为是由于 /fp:fast MSVC编译器选项,(除其他事项外)该选项允许编译器执行比较而无需考虑适当的NaN行为,以生成更快的代码.使用 /fp:precise

This prints the expected results: (NaN is formatted as -1.$ in the MSVC runtime)

 1.0  <  2.0 => true
 1.0  >  2.0 => false
 1.0 <=  2.0 => true
 1.0 >=  2.0 => false
 1.0 ==  2.0 => false
 1.0 !=  2.0 => true
-1.$  <  2.0 => false
-1.$  >  2.0 => false
-1.$ <=  2.0 => false
-1.$ >=  2.0 => false
-1.$ ==  2.0 => false
-1.$ !=  2.0 => true
 1.0  < -1.$ => false
 1.0  > -1.$ => false
 1.0 <= -1.$ => false
 1.0 >= -1.$ => false
 1.0 == -1.$ => false
 1.0 != -1.$ => true
-1.$  < -1.$ => false
-1.$  > -1.$ => false
-1.$ <= -1.$ => false
-1.$ >= -1.$ => false
-1.$ == -1.$ => false
-1.$ != -1.$ => true

However, when I paste this chunk of code down in the depths of my application's inner-loops, where all the floating-point computations are performed, I get these inexplicable results:

 1.0  <  2.0 => true
 1.0  >  2.0 => false
 1.0 <=  2.0 => true
 1.0 >=  2.0 => false
 1.0 ==  2.0 => false
 1.0 !=  2.0 => true
-1.$  <  2.0 => true
-1.$  >  2.0 => false
-1.$ <=  2.0 => true
-1.$ >=  2.0 => false
-1.$ ==  2.0 => true
-1.$ !=  2.0 => false
 1.0  < -1.$ => true
 1.0  > -1.$ => false
 1.0 <= -1.$ => true
 1.0 >= -1.$ => false
 1.0 == -1.$ => true
 1.0 != -1.$ => false
-1.$  < -1.$ => true
-1.$  > -1.$ => false
-1.$ <= -1.$ => true
-1.$ >= -1.$ => false
-1.$ == -1.$ => true
-1.$ != -1.$ => false

For some reason, the <, <=, and == operators are unexpectedly returning true when either or both arguments are NaN. Furthermore, the != operator is unexpectedly returning false.

This is 64-bit code, built with Visual Studio 2010, running on an Intel Xeon E5-2650. Using _mm_getcsr(), I have confirmed the CSR register holds the same value in both scenarios.

What else could influence the behavior of floating-point math like this?

解决方案

This behavior is due to the /fp:fast MSVC compiler option, which (among other things) permits the compiler to perform comparisons without regard to proper NaN behavior in an effort to generate faster code. Using /fp:precise or /fp:strict instead causes these comparisons to behave as expected when presented with NaN arguments.

这篇关于如果任一自变量是NaN,什么会使C/C ++&lt;,&lt; =和==运算符返回true?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆