使用 Infinity 和 NaN 禁用异常

Posted

技术标签:

【中文标题】使用 Infinity 和 NaN 禁用异常【英文标题】:Disable exception with Infinity and NaN 【发布时间】:2019-04-13 00:14:48 【问题描述】:

我有一个巨大的项目(不是我建造的),它允许有 InfinityNaN 值。尽管这是允许的,但这是不可取的。我read 这些值是由这些操作生成的:

1/0 = ∞
log (0) = -∞
sqrt (-1) = NaN

除此之外,当他们到达时,应该抛出一个FP Exception

如果我的项目允许对NaNInfinity进行操作,我认为SIGFPE会在某个地方处理,但我在整个项目中搜索并没有找到。

还有其他方法可以禁用此异常吗?我的目标是能够检测到这些值的第一次出现。

编辑: 我使用的是 Windows,我打算启用信号,但在启用之前,我想了解它是否被禁用。

【问题讨论】:

那么除以零的结果应该是什么? “还有其他方法可以禁用此异常吗?我的目标是能够检测到这些值的第一次出现。” 这不是说您实际上想要启用这个异常吗? 我不确定我是否理解正确:您是否希望抛出 SIGFPE?我正在使用 GCC,在我的安装中,它没有被抛出,而且我(还)找不到启用它的方法。 你在什么操作系统上运行? 来自您提到的 GCC 文档:当异常发生时(在引发异常时,以标准的语言),可能会发生以下两种情况之一。默认情况下,异常只是简单地在浮点状态字中注明,程序继续进行,就好像什么都没发生一样。该操作会产生一个默认值,这取决于异常 [...])。您的程序可以检查状态字以找出发生了哪些异常。 【参考方案1】:

我认为您不会遇到您所说的问题。默认情况下,不会引发 FP 异常。来自Windowsdocumentation:

默认情况下,系统已关闭所有 FP 异常。所以, 计算会导致 NAN 或 INFINITY,而不是异常。 在使用结构化捕获浮点 (FP) 异常之前 异常处理,必须调用_controlfp_sC运行库 函数打开所有可能的 FP 异常。仅诱捕 特殊例外,仅使用与 要捕获的异常。请注意,任何处理 FP 错误的处理程序都应该 调用 _clearfp 作为它的第一条 FP 指令。该功能清除 浮点异常。

GCC 也是如此,documentation 表示:

发生异常时(引发异常时,以 标准),可能会发生以下两种情况之一。默认情况下异常 只是在浮点状态字中注明,而程序 继续,好像什么事都没发生过。该操作产生一个默认值 值,这取决于异常 [...])。你的程序可以检查 状态字以找出发生了哪些异常。

要在您的 Windows 环境中启用异常(这将停止您的程序的执行),您可以尝试类似

#include <float.h>

int main() 
    _clearfp();
    unsigned int current_word = 0;
    _controlfp_s(&current_word, ~_EM_ZERODIVIDE, _MCW_EM);
    double div = 0.;
    double f = 1. / div;

对于非阻塞解决方案,请尝试使用 fenv.h,如 cppreference.com 上的 here 所述。

【讨论】:

也许我应该使用feraiseexcept 来启用? 我不明白您是要启用还是禁用例外。 现在我理解了上下文。我要启用。 请注意,纯 C 的 VC 支持带有 __try ... __except()... 的 SEH 您的程序将不会中止(但是,它不会告诉您异常发生的位置。为此,请删除 SEH 并运行程序在调试器中)。

以上是关于使用 Infinity 和 NaN 禁用异常的主要内容,如果未能解决你的问题,请参考以下文章

C语言中INF和NAN是啥意思

C语言 inf和nan

C语言 inf和nan

numpy nan和inf

强制 JSON.stringify() 发出这样做的 NaN / Infinity 或 JS JSON 库

java豆知识——NFINITY,-INFINITY和NAN