信号或捕捉';楠';当它们出现在c++; 我们用C++编写了数字代码。很少,但在某些特定输入下,某些计算会产生“nan”值

信号或捕捉';楠';当它们出现在c++; 我们用C++编写了数字代码。很少,但在某些特定输入下,某些计算会产生“nan”值,c++,debugging,exception-handling,nan,numerical-methods,C++,Debugging,Exception Handling,Nan,Numerical Methods,是否有标准或推荐的方法,当某个数值计算结果产生“nan”时,我们可以停止并提醒用户?(在调试模式下)。鉴于矩阵和向量的巨大规模,检查每个结果是否等于“nan”似乎不切实际 标准数字库如何处理这种情况?你能解释一下吗 测试f=使用启用-ffast数学优化的g++时,f可能会出现问题: 唯一简单的方法是检查位模式 至于在何处执行检查,这实际上取决于计算的具体情况以及Nan错误的频率,即在某些阶段继续受污染的计算与检查相比的性能损失。Nan在应用于数值操作时会传播。因此,检查作为NaN的最终结果就足够

是否有标准或推荐的方法,当某个数值计算结果产生“nan”时,我们可以停止并提醒用户?(在调试模式下)。鉴于矩阵和向量的巨大规模,检查每个结果是否等于“nan”似乎不切实际


标准数字库如何处理这种情况?你能解释一下吗

测试f=使用启用-ffast数学优化的g++时,f可能会出现问题:

唯一简单的方法是检查位模式


至于在何处执行检查,这实际上取决于计算的具体情况以及Nan错误的频率,即在某些阶段继续受污染的计算与检查相比的性能损失。

Nan在应用于数值操作时会传播。因此,检查作为NaN的最终结果就足够了。至于如何做,如果为>=C++11构建,正如Goz所注意到的,有std::isnan。对于
         ?  11.......1  xx.......x
sign bit ^  ^exponent^  ^fraction^
在哪里?可以是任何值,并且至少一个x必须是1


对于依赖于平台的解决方案,还有另一种可能性。glibc中有一个函数
feenableexcept
(可能带有
signal
函数和编译器选项
-fnon-call exceptions
),当发生无效浮点操作时,该函数会开启一代
SIGFPE
sinals。函数
\u control87
(可能使用
\u set\u se\u translator
函数和编译器选项
/EHa
),它在VC中允许几乎相同的操作。

在许多体系结构上,您可以取消无效异常的掩码,这将导致一个中断,当一个NaN通常是由一个计算生成的,比如
0*infinity
。在调试器中运行时,您将中断此中断,并可以检查导致该点的计算。在调试器之外,可以安装陷阱处理程序来记录有关生成无效操作的计算状态的信息

例如,在x86上,您可以清除FPCR(位0)和MXCSR(位7)中的无效操作掩码位,以分别对x87和SSE操作中的无效操作启用捕获


一些单独的平台提供了从C写入这些控制寄存器的方法,但是没有跨平台工作的可移植接口。

尽管这是最初由glibc提供的非标准扩展,在许多系统上,您可以使用
中声明的
feenableexcept
例程请求机器捕获特定的浮点异常,并将
SIGFPE
传递到您的进程。您可以使用
fedisableexcept
屏蔽捕获,并使用
fegetexcept
查询未屏蔽的异常集。默认情况下,它们都是屏蔽的

在没有这些例程的旧BSD系统上,您可以使用
中的
fpsetmask
fpgetmask
,但这个世界似乎正在向glibc API靠拢


警告:glibc目前有一个bug,即(C99标准例程)
fegetenv
具有屏蔽x86上所有异常陷阱的意外副作用,因此您必须调用
fesetenv
,以在以后恢复它们。(向你展示了人们对这些东西的依赖程度……

事实上,正是这种传播方式让事情变得更加困难。如果您想在一个示例中找到它首先出现的位置,比如说1000行代码,分为多个类(显然它们之间共享计算值),该怎么办。你明白了吗?我想知道是否还有其他人面临这个问题,如果是的话,他们是如何处理的。@MhAcKNI,所以,不幸的是,你不得不依赖一个依赖于平台的解决方案。正如Stephen Canon提到的,没有通用接口。至少,我没有意识到这一点。如果您的目标是Windows或Unix,请尝试上述方法。