NAN -> 区分除以零和具有非常大的负值的指数
NAN -> distinguish between a division by zero and an exponent with a very large negative value
我在我的测试套件中包含了一个 。
现在在下一行抛出一个 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 扩展;non-standard)。
,否则将普通浮点数除以零不会产生信号。
在标准 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);
我在我的测试套件中包含了一个
现在在下一行抛出一个 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 扩展;non-standard)。
在标准 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);