在Visual C 2013中,x64版本的浮动负无穷大的std :: exp返回负无穷大

使用std :: exp来计算e ^ -infinity返回-infinity,当使用无穷大的浮点数表示,并使用Visual C 2013构建一个x64二进制文件.我希望它返回0,这是Win32构建或版本的std :: exp需要一个double.

下面的代码,构建为x64,演示了这个问题.

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

用于编译的命令行选项(取自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"

产量以上:

exp of float -infinity: -1.#INF
exp of double -infinity: 0

为什么会发生这种情况?

解决方法

我通常会说这是一个描述的错误,因为C11对于cmath功能而言是C99,而C99在F.9.3.1中明确指出exp(-∞)返回0.然而,请记住,在附件标准规定:

An implementation that defines __STDC_IEC_559__ shall conform to the specifications in this annex.

在MSVC中,32位或64位模式似乎并未定义该宏,因此它可能不是错误,您可能会失去运气. / fp:strict和/ fp:精准之间也不会改变浮点模式,使事情变得更好.

在所有情况下,结果似乎在32位和64位目标之间有所不同,并且基于标准,它只表示exp将计算x的base-e指数,似乎没有要求如何,似乎是可以的.

如果您在快速修复后,使用pow函数似乎可以生成正确的结果:

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

无论您是否拥有64位/ 32位,调试/释放或fp:精确/ fp:strict,这两个行都会生成零,但是无论是否保证,我都不能说.

相关文章

/** C+⬑ * 默认成员函数 原来C++类中,有6个默认成员函数: 构造函数 析构函数 拷贝...
#pragma once // 1. 设计一个不能被拷贝的类/* 解析:拷贝只会放生在两个场景中:拷贝构造函数以及赋值运...
C类型转换 C语言:显式和隐式类型转换 隐式类型转化:编译器在编译阶段自动进行,能转就转,不能转就编译...
//异常的概念/*抛出异常后必须要捕获,否则终止程序(到最外层后会交给main管理,main的行为就是终止) try...
#pragma once /*Smart pointer 智能指针;灵巧指针 智能指针三大件//1.RAII//2.像指针一样使用//3.拷贝问...
目录&lt;future&gt;future模板类成员函数:promise类promise的使用例程:packaged_task模板类例程...