如何引发浮点异常

Posted

技术标签:

【中文标题】如何引发浮点异常【英文标题】:How to raise a float point exception 【发布时间】:2013-05-20 22:35:59 【问题描述】:

伙计们。我正在围绕浮点运算做一些工作。 0.1 不精确地用二进制浮点格式表示。于是我写下了这个

float i = 0.1f;

并期望出现不精确的异常。我打开了 -fp-trap-all=all 选项,将 fp-mode 设置为严格并在我的代码中安装了 SIGFPE 信号处理程序。但是什么也没发生。然后我尝试了

float i = 0.1f,j = 0.2f, c;
c = i + j;

仍然无法捕获任何异常!它让我发疯。

抱歉,我终于在 Linux 上使用了 intel c++ 编译器。

【问题讨论】:

“浮点异常”...我认为这个词并不代表你的想法。 @KerrekSB 但我尝试了本质上不精确的 sin 函数。但是我什么也没看到,我的程序没有捕获异常就退出了。 函数怎么会“本质上不精确”? @KerrekSB 因为我使用了一个肯定会产生无理数的值。 0.1f decimal->binary 不是在编译时执行的吗?在这种情况下,您在运行时没有遇到任何异常似乎很正常......除非您使用 float i=atof('0.1'); 进行初始化 【参考方案1】:

您必须自己测试异常。以下代码works for me:

#include <stdio.h>
#include <fenv.h>

#ifndef FE_INEXACT
#  error No FP Exception handling!
#endif

int main()

    double a = 4.0;
    a /= 3.0;

    if (fetestexcept(FE_INEXACT) & FE_INEXACT)
    
        printf("Exception occurred\n");
    
    else
    
        printf("No exception.\n");
    

如果将4.0 替换为3.0,则不会出现异常。

你可以用double a = 0.0; a = sin(a);做类似的事情。


仅有条件地支持捕获异常。要检查,请使用文档中描述的宏:

#define _GNU_SOURCE
#include <fenv.h>

#ifndef FE_NOMASK_ENV
#  warning Cannot raise FP exceptions!
#else
#  warning Trapping FP exceptions enabled.
feenableexcept(FE_INEXACT);
#endif

【讨论】:

我的代码中需要调用feenableexcept。异常出现后调用了我的处理程序。您的代码似乎没有调用处理程序,但设置了标志。我认为 ieee754 提到了“异常的备用处理程序”。我的处理程序可以被视为“备用处理程序”吗?尽管您对异常做了一些处理,但您的代码没有。 这是一个很好的例子。它给了我一些灵感,非常感谢。 @iqapple:处理器支持异常(或陷阱)这一事实并不意味着在该处理器上执行的 C 实现支持它们。 一些需要注意的术语:在 IEEE 754 浮点标准中,当操作没有合适的结果时会发生异常;例如,精确的数学结果超出了浮点格式表示它的能力。异常可能导致替换结果(接近的值、无穷大、NaN 或其他)、标志和/或陷阱。在其他情况下,异常可能是指程序控制的某种变化,通常是由于程序错误。 作为标准C,这段代码应该在#include &lt;fenv.h&gt;之后包含#pragma STDC FENV_ACCESS on,以通知编译器代码可以测试浮点状态标志或者可以使用非默认浮点控制运行模式。但是,编译器可能会采用默认浮点运算,这会影响代码生成。但是,常见的编译器可能还不支持这一点。【参考方案2】:

根据this answer,仅当浮点数的舍入版本与数学上的精确数值不同时才会引发不精确异常。在您的情况下,四舍五入的响应是相同的,因此不会引发异常。

【讨论】:

但我尝试了本质上不精确的 sin 函数。但是我什么也没看到,我的程序没有捕获异常就退出了。 好的,我知道了。我得到了不确切的例外。谢谢你的帮助。我还需要调用feenableexcept。

以上是关于如何引发浮点异常的主要内容,如果未能解决你的问题,请参考以下文章

使用pow时如何避免浮点异常? [关闭]

在 MinGW GCC 上启用浮点异常?

浮点异常(核心转储)#694457

在混合 C/Fortran 代码中捕获浮点异常

C:无序浮点比较不会引发 FE_INVALID

没有浮点或双变量的浮点异常