【问题标题】:std::exp(-100.0f) == NaN?std::exp(-100.0f) == NaN?
【发布时间】:2018-09-03 04:02:32
【问题描述】:

g++ 版本 (5.4.0) 为 std::exp 返回 NaN,浮点数小于大约 87。

但是docs to std::exp 建议,它接近0 对于小数字:

如果参数是-∞,则返回+0

这是标准库实现中的错误,还是我缺少什么?

效果可以是reproduced这样的:

#include <cmath>
#include <fenv.h>
#include <iostream>

int main()
{
    feenableexcept(FE_ALL_EXCEPT & ~FE_INEXACT);
    for (float x = 30; x > -1000; --x)
    {
        float y = std::exp(x);
        std::cout << x << "\t\t" << y << std::endl;
    }
}

输出:

30              1.06865e+13
29              3.93133e+12
28              1.44626e+12
27              5.32048e+11
...
-84             3.3057e-37
-85             1.2161e-37
-86             4.47378e-38
-87             1.64581e-38
Floating point exception

【问题讨论】:

  • 在您的示例中触发的 feexp 可能是一些下溢异常,顺便说一句。不过,这不会产生 NaN,而是先产生次正规数,然后产生 0。
  • 如果你使用了double 重载,它会在-708 之后导致下溢。或者 -708.4 表示 IEEE 兼容的 double 准确地说。

标签: c++ gcc floating-point g++ nan


【解决方案1】:

您指定FE_UNDERFLOW 先前的浮点运算的结果是不正常的,精度损失FE_ALL_EXCEPT 的位标志之一)。 float 可以表示的不为零的最小值是1e-38。在x 达到-88 后,您会得到浮点异常,而结果是小于1e-386.0546e-39。不是NaN,您使用指令feenableexcept(FE_ALL_EXCEPT &amp; ~FE_INEXACT) 调整了异常的引发。

如果您删除位标志FE_UNDERFLOW,您的循环将输出零(或小的非零值,具体取决于平台)。

【讨论】:

  • 如果float最小值为1.17549e-38cout函数如何显示6.0546e-39
  • @MatthieuH 请展示 cout 可以显示浮点值 6.0546e-39 的示例。
猜你喜欢
  • 2012-05-20
  • 1970-01-01
  • 2017-06-22
  • 2020-07-29
  • 1970-01-01
  • 2013-07-15
  • 2014-02-11
  • 1970-01-01
  • 2019-05-17
相关资源
最近更新 更多