为什么释放/debugging对std :: min有不同的结果?

这里是testing程序:

void testFunc() { double maxValue = DBL_MAX; double slope = std::numeric_limits<double>::quiet_NaN(); std::cout << "slope is " << slope << std::endl; std::cout << "maxThreshold is " << maxValue << std::endl; std::cout << "the_min is " << std::min( slope, maxValue) << std::endl; std::cout << "the_min is " << std::min( DBL_MAX, std::numeric_limits<double>::quiet_NaN()) << std::endl; } int main( int argc, char* argv[] ) { testFunc(); return 0; } 

在debugging中,我得到:

 slope is nan maxThreshold is 1.79769e+308 the_min is nan the_min is 1.79769e+308 

在发布中,我得到:

 slope is nan maxThreshold is 1.79769e+308 the_min is 1.79769e+308 the_min is nan 

为什么我会在debugging版本中获得不同的结果?

我已经检查过堆栈溢出文章在C ++中使用最小和最大函数 ,并没有提及任何版本/debugging差异。

我正在使用Visual Studio 2015。

在IEEE 754比较NAN的东西总是会产生false ,不pipe它是什么。

 slope > 0; // false slope < 0; // false slope == 0; // false 

而且,对你更重要

 slope < DBL_MAX; // false DBL_MAX < slope; // false 

因此,编译器似乎重新sorting参数/使用><=而不是< ,这就是为什么你得到不同的结果。

例如,这些function可以这样描述

发布:

 double const& min(double const& l, double const r) { return l <= r ? l : r; } 

debugging:

 double const& min(double const& l, double const& r) { return r < l ? r : l; } 

撇开std::min的要求(LessThanComparable),这些在算术上有相同的含义。 但是,当您将它们用于NaN时,它们会产生不同的结果。

得到它了:

这里是VS在debugging模式下使用的实现( _PredDEBUG_LT ,LT为低于):

 template<class _Pr, class _Ty1, class _Ty2> inline _CONST_FUN bool _Debug_lt_pred(_Pr _Pred, _Ty1&& _Left, _Ty2&& _Right, _Dbfile_t _File, _Dbline_t _Line) { // test if _Pred(_Left, _Right) and _Pred is strict weak ordering return (!_Pred(_Left, _Right) ? false : _Pred(_Right, _Left) ? (_DEBUG_ERROR2("invalid comparator", _File, _Line), true) : true); } 

相当于(更可读):

  if (!_Pred(_Left, _Right)) { return false; } else { if ( _Pred(_Right, _Left) ) { assert( false ); return true; } else { return true; } } 

其中,再次相当于(!_Pred(_Left, _Right)) 。 作为macros转换,它变成#define _DEBUG_LT(x, y) !((y) < (x)) (即:不是正确的<左)。

释放实现实际上是一个macros#define _DEBUG_LT(x, y) ((x) < (y)) (即:left <right)。

所以Debug (!(y<x))和Release (x<y)实现是绝对不一样的,如果一个参数是NaN,它们的行为将会不同。 不要问为什么他们这样做….

您没有指定处理器使用哪种浮点表示格式。 但是,既然您使用Visual Studio,我会假定您使用Windows,然后我假设您的处理器使用IEEE 754表示。

在IEEE 754中,NaN对每个数字都是无序的。 这意味着对于(NaN < f) == false的任何值, (NaN < f) == false(f < NaN) == false 。 迂回地说,这意味着支持NaN的浮点数不能满足std::min要求的LessThanComparable的要求。 实际上, std::min行为与标准中的规定相同,只要这两个参数都不是NaN即可。

由于其中一个参数是代码中的NaN,所以标准没有指定结果 – 它可以是一个或另一个,取决于任何外部因素,如发布版本与debugging版本,编译器版本,月相等等。