我在测试套件中包含了check for nan's。
现在,将SIGFPE引发在以下行中
const double retVal =exp(exponent);
指数的值约为-4000。当然,这非常接近于零,并且如果不进行nan检查,则计算将以零继续进行。
现在抛出信号SIGFPE。我假设这是一个denormal number(表示为NAN)。
如何区分零除和负值很大的指数?
在第二种情况下,由于我不需要区分+0和-0,因此在我的情况下可以使用零进行进一步的计算。
编辑:
我尝试了@ user2079303的建议。我的代码看起来像这样
#include <signal.h>
void fpe_handler(int signo, siginfo_t *info, void *context) {
switch(info->si_code) {
case FPE_INTDIV: // division by zero
break;
case FPE_FLTUND: // underflow
break;
// other cases ...
}
}
int main() {
struct sigaction action = {};
action.sa_flags = SA_SIGINFO;
action.sa_sigaction = fpe_handler;
sigaction(SIGFPE, &action, NULL);
const double a = 0.0/0.0;
if (a>0)
return 0;
else
return 1;
}
这样可以编译,但不会引发信号或错误消息。
最佳答案
从C++的角度来看,从技术上讲,被零除具有不确定的行为,因此没有标准的处理方法。
在无处不在的IEEE 754标准中,以零除的定义很明确,不会产生信号。可以使用<cfenv>
header 测试先前执行的计算是否被零除:
std::feclearexcept(FE_ALL_EXCEPT);
// do calculation here
if(std::fetestexcept(FE_DIVBYZERO)) {
// I was just divided by zero. The sky is falling.
std::abort();
} else if(std::fetestexcept(FE_UNDERFLOW)) {
// I just underflowed. This is my life now.
}
现在,将普通浮点数除以零不会产生信号,除非您要求使用
feenableexcept
(这是GNU扩展;非标准)。在标准C++中,无法区分SIGFPE的不同原因。但是有a way in POSIX标准:
void fpe_handler(int signo, siginfo_t *info, void *context)
{
switch(info->si_code) {
case FPE_FLTDIV: // division by zero
break;
case FPE_FLTUND: // underflow
break;
// other cases ...
}
}
// registering
struct sigaction action = {};
action.sa_flags = SA_SIGINFO;
action.sa_sigaction = fpe_handler;
sigaction(SIGFPE, &action, NULL);