feclearexcept

< c‎ | numeric‎ | fenv
定义于头文件 <fenv.h>
int feclearexcept( int excepts );
(C99 起)

尝试清除列于位掩码参数 excepts 的浮点异常,该参数值为浮点异常宏的逐位或。

参数

excepts - 列出带清除的异常标志的位掩码

返回值

若成功清除所有指明的异常,或若 excepts 为零则返回 0 。错误时返回非零。

示例

#include <fenv.h>
#include <stdio.h>
#include <math.h>
#include <float.h>
 
/*
 * 可能的hypot实现,它会活用许多高级浮点特性。
 */
double hypot_demo(double a, double b) {
  const int range_problem = FE_OVERFLOW | FE_UNDERFLOW;
  feclearexcept(range_problem);
  // 尝试快速算法
  double result = sqrt(a * a + b * b);
  if (!fetestexcept(range_problem))  // 未上溢或下溢
    return result;                   // 返回结果
  // 做更多复杂计算以避免上溢或下溢
  int a_exponent,b_exponent;
  frexp(a, &a_exponent);
  frexp(b, &b_exponent);
 
  if (a_exponent - b_exponent > DBL_MAX_EXP)
    return fabs(a) + fabs(b);        // 我们可以忽略小值
  // 令fabs(a)的规模接近1
  double a_scaled = scalbn(a, -a_exponent);
  double b_scaled = scalbn(b, -a_exponent);
  // 现在上溢和下溢是不可能的
  result = sqrt(a_scaled * a_scaled + b_scaled * b_scaled);
  // 撤销规模化
  return scalbn(result, a_exponent);
}
 
int main(void)
{
  // 通常情况选择较快的路线
  printf("hypot(%f, %f) = %f\n", 3.0, 4.0, hypot_demo(3.0, 4.0));
  // 极限情形会选择较慢但更准确的路线
  printf("hypot(%e, %e) = %e\n", DBL_MAX / 2.0, 
                                DBL_MAX / 2.0, 
                                hypot_demo(DBL_MAX / 2.0, DBL_MAX / 2.0));
 
  return 0;
}

输出:

hypot(3.000000, 4.000000) = 5.000000
hypot(8.988466e+307, 8.988466e+307) = 1.271161e+308

引用

  • C11 standard (ISO/IEC 9899:2011):
  • 7.6.2.1 The feclearexcept function (p: 209)
  • C99 standard (ISO/IEC 9899:1999):
  • 7.6.2.1 The feclearexcept function (p: 190)

参阅

确认设置了哪些浮点异常状态标志
(函数)