jpo*_*o38 41 c++ nan min floating-point-comparison
这是测试程序:
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;
}
Run Code Online (Sandbox Code Playgroud)
在Debug中,我得到:
slope is nan
maxThreshold is 1.79769e+308
the_min is nan
the_min is 1.79769e+308
Run Code Online (Sandbox Code Playgroud)
在发布中,我得到:
slope is nan
maxThreshold is 1.79769e+308
the_min is 1.79769e+308
the_min is nan
Run Code Online (Sandbox Code Playgroud)
为什么我会在Release中获得与调试不同的结果?
我已经检查了Stack Overflow post C++中使用min和max函数,并没有提到任何Release/Debug差异.
我正在使用Visual Studio 2015.
krz*_*zaq 37
在IEEE 754中,将NAN与任何东西进行比较false
,无论它是什么,总会产生.
slope > 0; // false
slope < 0; // false
slope == 0; // false
Run Code Online (Sandbox Code Playgroud)
而且,更重要的是对你而言
slope < DBL_MAX; // false
DBL_MAX < slope; // false
Run Code Online (Sandbox Code Playgroud)
因此,似乎编译器重新排序参数/使用>
或<=
代替<
,这就是为什么你得到不同的结果.
例如,这些功能可以这样描述
发布:
double const& min(double const& l, double const r) {
return l <= r ? l : r;
}
Run Code Online (Sandbox Code Playgroud)
调试:
double const& min(double const& l, double const& r) {
return r < l ? r : l;
}
Run Code Online (Sandbox Code Playgroud)
除了要求(LessThanComparable)std::min
之外,那些具有相同意义的算术.但是当它们与NaN一起使用时,它们会产生不同的结果.
jpo*_*o38 26
得到它了:
这是在调试模式下使用VS(与实施_Pred
是DEBUG_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);
}
Run Code Online (Sandbox Code Playgroud)
这相当于(更具可读性):
if (!_Pred(_Left, _Right))
{
return false;
}
else
{
if ( _Pred(_Right, _Left) )
{
assert( false );
return true;
}
else
{
return true;
}
}
Run Code Online (Sandbox Code Playgroud)
其中,再次相当于(!_Pred(_Left, _Right))
.转录为宏,它变为#define _DEBUG_LT(x, y) !((y) < (x))
(即:不是右<左).
发布实现实际上是一个宏#define _DEBUG_LT(x, y) ((x) < (y))
(即:左<右).
所以调试(!(y<x))
和发布(x<y)
实现肯定不一样,如果一个参数是NaN,它们的行为会有所不同......!不要问他们为什么那样做......
eer*_*ika 22
您没有指定处理器使用哪种浮点表示格式.但是,既然你使用Visual Studio,我会假设你使用Windows,然后我假设你的处理器使用IEEE 754表示.
在IEEE 754中,NaN对于每个数字都是无序的.这意味着(NaN < f) == false
和(f < NaN) == false
任何价值f
.小心地说,这意味着支持NaN的浮点数不符合LessThanComparable的要求std::min
.std::min
只要两个参数都不是NaN,实际上就会按照标准中的规定行事.
由于其中一个参数是代码中的NaN,因此标准未指定结果 - 它可能是一个或另一个,具体取决于任何外部因素,如发布与调试版本,编译器版本,月相等.
归档时间: |
|
查看次数: |
3263 次 |
最近记录: |