tutorial smart remix español curso aprender c++ nan min floating-point-comparison

c++ - smart - ¿Por qué Release/Debug tiene un resultado diferente para std:: min?



solidity español (3)

Aquí está el programa de prueba:

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; }

En la depuración, obtengo:

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

En la versión, obtengo:

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

¿Por qué obtendría un resultado diferente en Release que Debug?

Ya revisé la publicación de Stack Overflow Uso de las funciones mín. Y máx. En C ++ , y no menciona las diferencias de Release / Debug.

Estoy usando Visual Studio 2015.


En IEEE 754, comparar NAN con cualquier cosa siempre arrojará resultados false , sin importar de qué se trate.

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

Y, más importante para ti

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

Por lo tanto, parece que el compilador reordena los parámetros / usos > o <= lugar de < , y es por eso que obtienes los resultados diferentes.

Por ejemplo, esas funciones podrían describirse como tales

Lanzamiento:

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

Depurar:

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

Los requisitos (LessThanComparable) en std::min un lado, tienen el mismo significado aritméticamente. Pero producen resultados diferentes cuando los usas con NaN.


Lo tengo:

Aquí está la implementación utilizada por VS en el modo de depuración (con _Pred siendo DEBUG_LT , LT para Lower Than):

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); }

Que es equivalente a (más legible):

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

Cuál, otra vez es equivalente a (!_Pred(_Left, _Right)) . Transcrito como una macro, se convierte en #define _DEBUG_LT(x, y) !((y) < (x)) (es decir: NO derecha <izquierda).

La implementación de la versión es en realidad una macro #define _DEBUG_LT(x, y) ((x) < (y)) (es decir, left <right).

Así que las implementaciones Debug (!(y<x)) y Release (x<y) definitivamente no son las mismas y se comportan de manera diferente si un parámetro es un NaN ...! No preguntes por qué lo hicieron ...


No especificó qué formato de representación de coma flotante usa su procesador. Pero, como usa Visual Studio, supondré que usa Windows, y luego asumiré que su procesador usa representación IEEE 754 .

En IEEE 754, NaN no está ordenado con respecto a cada número. Esto significa que (NaN < f) == false y (f < NaN) == false para cualquier valor de f . Pedagógicamente, esto significa que los números de coma flotante que admiten NaN no cumplen los requisitos de LessThanComparable que es un requisito para std::min . Prácticamente std::min comporta como se especifica en el estándar siempre que ninguno de los argumentos sea NaN.

Como uno de los argumentos es NaN en su código, el resultado no está especificado por el estándar; podría ser uno o el otro dependiendo de factores externos como la versión frente a la versión de depuración, la versión del compilador, la fase de la luna, etc.