Using std::exp
to calculate e^-infinity
returns -infinity
when using the float representation of infinity and building an x64 binary using Visual C++ 2013. I would expect it to return 0, which is what happens with Win32 builds, or the version of std::exp
that takes a double
.
The following code, built as x64, demonstrates the issue.
#include <limits>
#include <iostream>
int main(const int argc, const char** argv) {
std::cout << "exp of float -infinity: " << std::exp(-std::numeric_limits<float>::infinity()) << std::endl;
std::cout << "exp of double -infinity: " << std::exp(-std::numeric_limits<double>::infinity()) << std::endl;
}
Command line options for compile (taken from Visual Studio):
/GS /Wall /Gy /Zc:wchar_t /Zi /Gm- /Od /sdl /Fd"x64\Release\vc120.pdb" /fp:precise /D "_MBCS" /errorReport:prompt /WX /Zc:forScope /Gd /Oi /MD /Fa"x64\Release\" /EHsc /nologo /Fo"x64\Release\" /Fp"x64\Release\NumericLimitsTest.pch"
Output of above:
exp of float -infinity: -1.#INF
exp of double -infinity: 0
Why does this happen?
I would normally say that was a bug of some description, since C++11 defers to C99 for cmath
functionality and C99 clearly states in F.9.3.1
that exp(−∞) returns +0
. However, keep in mind that's in an annex of the standard which states:
An implementation that defines
__STDC_IEC_559__
shall conform to the specifications in this annex.
That macro doesn't appear to be defined in either 32- or 64-bit mode in MSVC so it's probably not a bug and you may be out of luck. Nor does changing the floating point mode between /fp:strict
and /fp:precise
make things any better.
In all cases, the result seems to differ between 32-bit and 64-bit target and, based on the standard which only states that exp
will compute the base-e exponential of x
with seemingly no requirement on how, it seems to be okay.
If you're after a quick fix, using the pow
function seems to generate the correct results:
#define DBL_E 2.71828182845904523536
#define FLT_E 2.71828182845904523536f
std::cout
<< "exp of float -infinity: "
<< std::pow(FLT_E, -std::numeric_limits<float>::infinity())
<< std::endl;
std::cout
<< "exp of double -infinity: "
<< std::pow(DBL_E,-std::numeric_limits<double>::infinity())
<< std::endl;
This generates zero for both lines regardless of whether you have 64-bit/32-bit
, debug/release
or fp:precise/fp:strict
but, whether that's guaranteed, I couldn't say.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With