【问题标题】:floating point exception is thrown when casting double to int将 double 转换为 int 时抛出浮点异常
【发布时间】:2019-07-02 03:15:41
【问题描述】:

考虑这段代码:

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

int main()
{
    feenableexcept(FE_INVALID);
    double d = INT_MAX * 2.0f;
    int i = (int)d; // it throws here fp exception and terminates. Why ?

    std::cout << i << std::endl;

    return 0;
}

这里首先要注意的是,将 double 转换为 int 会导致临时值溢出(大于 INT_MAX),这当然通常是未定义的行为。

但我更担心的是,这里的 FP 异常可以通过将FE_INVALID 常量标志传递给feenableexcept 函数来捕获。

cpp_reference可以看出FE_INVALID和溢出根本没有关系。

为什么这里的整数溢出会导致fp异常?

这是因为 UB 的性质吗?

【问题讨论】:

  • INT_MAX * 2.0f 可以表示为float 吗?你为什么用2.0f而不是2.0
  • @SidS 确实有点奇怪的选择,但它适合。 FLT_MAX 通常是 3.40282e+38。
  • @BaummitAugen 当然可以,但是会缺少精度? INT_MAX * 2.0f / 2 可能不等于 INT_MAX
  • @BaummitAugen,在我的系统上这个代码:cout &lt;&lt; INT_MAX &lt;&lt; ' ' &lt;&lt; int(INT_MAX * 2.0f / 2) &lt;&lt; ' ' &lt;&lt; int(INT_MAX * 2.0 / 2) &lt;&lt; endl; 输出2147483647 -2147483648 2147483647
  • 请注意常见的混淆来源。浮点异常不是 C++ 异常,因此不会被抛出。浮点数的人称错误为异常,但它们是两个不同的东西。

标签: c++ c++11 exception floating-point integer-overflow


【解决方案1】:

由于这是 C++ 标准的 UB,当然语言本身没有指定。

但是,在这方面,您的实现遵循 IEEE-754(大多数实现基于其浮点行为的标准),其中指出:

当 NaN 或无限操作数不能以目标格式表示时,否则不能 被指示,无效操作异常应发出信号。 当数字操作数转换为 超出目标格式范围的整数,如果出现无效操作异常,则应发出信号 这种情况不能以其他方式表示。

(5.8“从浮点到整数格式转换的详细信息”,强调我的)

发出信号时如何处理这些异常留给实现;为他们设置陷阱是其中一种可能性。

延伸阅读:gcc's documentation on FP exceptions

【讨论】:

    猜你喜欢
    • 2010-09-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-02
    • 2011-05-10
    • 1970-01-01
    • 2017-05-17
    相关资源
    最近更新 更多