如果您正在构建计算器接口并希望处理浮点异常,则应该:
在任何浮点运算之前重置标志
操作后
测试标志
你没有任何帮助,所以你必须手工实施 . 示例:
double mul(double a, double b, int *status) {
#pragma STDC FENV_ACCESS ON
fexcept_t flags;
int sv_status, f_status = -1;
double resul;
sv_status = fegetexceptflag(&flags, FE_ALL_EXCEPT) != 0; /* save flags */
if (sv_status == 0) {
f_status = feclearexcept(FE_ALL_EXCEPT); /* clear all fp exception con
ditions */
}
resul = a * b;
if (f_status == 0) {
*status = fetestexcept(FE_ALL_EXCEPT); /* note conditions */
}
if (sv_status == 0) {
fesetexceptflag(&flags, FE_ALL_EXCEPT); /* restore initial flags */
}
return resul;
}
演示:
int main ()
{
double d2, d3, d4;
int status;
double d = 1e100;
feraiseexcept(FE_OVERFLOW | FE_INEXACT);
status = fetestexcept(FE_ALL_EXCEPT);
printf("initial status : %x\n", status);
d2 = mul(3., 4., &status);
printf("resul 3 * 4 : %g - status %x (%x)\n", d2,
status, fetestexcept(FE_ALL_EXCEPT));
d2 = mul(d, d, &status);
printf("resul d * d : %g - status %x (%x)\n", d2,
status, fetestexcept(FE_ALL_EXCEPT));
d2 = mul(d2, d, &status);
printf("resul d *d *d : %g - status %x (%x)\n", d2,
status, fetestexcept(FE_ALL_EXCEPT));
d2 = mul(d2, d, &status);
printf("resul d *d *d*d : %g - status %x (%x)\n", d2,
status, fetestexcept(FE_ALL_EXCEPT));
d2 = mul(d2, d, &status);
printf("resul d *d *d*d*d : %g - status %x (%x)\n", d2,
status, fetestexcept(FE_ALL_EXCEPT));
return 0;
}
给出:
initial status : 28
resul 3 * 4 : 12 - status 0 (28)
resul d * d : 1e+200 - status 20 (28)
resul d *d *d : 1e+300 - status 20 (28)
resul d *d *d*d : inf - status 28 (28)
resul d *d *d*d*d : inf - status 0 (28)
这意味着 mul :
正确设置状态标志
保持浮点异常标志不变
由于此代码仅使用C规范中定义的宏和函数,因此它应该适用于任何符合C99的编译器 .
现在由你来实际处理旗帜了 .
Nota:Clang(至少)发出一个警告说它忽略了pragma STDS FENV_ACCESS,但它工作正常