Namespaces
Variants

feclearexcept

From cppreference.net
< c ‎ | numeric ‎ | fenv
ヘッダー <fenv.h> で定義
int feclearexcept ( int excepts ) ;
(C99以降)

引数 excepts でリストされた浮動小数点例外をクリアしようと試みます。 excepts 浮動小数点例外マクロ のビット単位のORです。

目次

パラメータ

excepts - クリアする例外フラグをリストするビットマスク

戻り値

0 すべての指定された例外が正常にクリアされた場合、または excepts がゼロの場合。エラー時には非ゼロの値を返します。

#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規格 (ISO/IEC 9899:2011):
  • 7.6.2.1 feclearexcept関数 (p: 209)
  • C99規格 (ISO/IEC 9899:1999):
  • 7.6.2.1 feclearexcept関数 (p: 190)

関連項目

指定された浮動小数点ステータスフラグのうち設定されているものを判定する
(関数)
C++ドキュメント for feclearexcept