【问题标题】:std::exp of float negative infinity returns negative infinity for x64 builds in Visual C++ 2013浮点负无穷大的 std::exp 返回负无穷大,用于 Visual C++ 2013 中的 x64 构建
【发布时间】:2015-09-23 05:56:57
【问题描述】:

当使用无穷大的浮点表示并使用 Visual C++ 2013 构建 x64 二进制文件时,使用 std::exp 计算 e^-infinity 将返回 -infinity。我希望它返回 0,这与 Win32 版本相同,或者采用doublestd::exp 版本。

以下构建为 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

为什么会这样?

【问题讨论】:

  • 这是一个错误;它已在 Visual C++ 2015 运行时库中修复。
  • @JamesMcNellis - 这不是最终的答案吗?

标签: c++ visual-c++


【解决方案1】:

我通常会说这是某种描述的错误,因为 C++11 在 cmath 功能上遵循 C99,而 C99 在 F.9.3.1 中明确指出 exp(−∞) returns +0。但是,请记住,该标准的附件中规定:

定义__STDC_IEC_559__ 的实现应符合本附件中的规范。

在 MSVC 中,该宏似乎没有在 32 位或 64 位模式下定义,因此它可能 不是 一个错误,您可能不走运。在 /fp:strict/fp:precise 之间更改浮点模式也不会让事情变得更好。

在所有情况下,结果似乎在 32 位和 64 位目标之间有所不同,并且基于仅规定 expcompute the base-e exponential of x 的标准,似乎对如何没有要求,这似乎没问题.


如果您想要快速修复,使用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-bit/32-bitdebug/releasefp:precise/fp:strict,这都会为两条线生成零,但是,这是否有保证,我不能说。

【讨论】:

  • 附件F的全部内容不是可选的吗?
  • @hvd,取决于 MSVC 是否定义了_ _STDC_IEC_559_ _。我没有在本地安装它,所以无法检查。我会更新答案。
  • score++ 这可能确实是一个严格/精确的问题。
  • cl 版本 18.00.31010 (VS 2013) 开始,未定义预定义宏 __STD_IEC_559__。此外,VC++ 因其不符合 C99 标准而闻名:)
猜你喜欢
  • 2013-11-29
  • 2012-02-09
  • 1970-01-01
  • 2010-11-03
  • 2017-08-19
  • 2015-03-22
  • 1970-01-01
  • 2019-12-31
  • 1970-01-01
相关资源
最近更新 更多