#include <math.h> #include <errno.h> #include <fenv.h>
移植性が必要なプログラムで、数学関数からのエラーを確認する必要がある場合には、 数学関数を呼び出す前に errno を 0 に設定し、
feclearexcept(FE_ALL_EXCEPT);
を呼び出すべきである。
数学関数から返ってきた際に、 errno が 0 以外か、
fetestexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW |
FE_UNDERFLOW);
の呼び出しが 0 以外を返した場合 (fenv(3) 参照)、数学関数でエラーが発生している。
浮動小数点のオーバーフローは、結果が有限だが、大き過ぎて 結果を返す型では表現できない場合に発生する。 オーバーフローが発生すると、 その関数は HUGE_VAL, HUGE_VALF, HUGE_VALL のいずれかを返す (前記の値のうちどれが返るかは関数の返り値の型により決まり、 それぞれ double, float, long double に対応する)。 errno は ERANGE に設定され、「オーバーフロー (overflow)」 浮動小数点例外 (FE_OVERFLOW) が上がる。
浮動小数点のアンダーフローは、 結果が小さ過ぎて、結果を返す型では表現できない場合に発生する。 アンダーフローが発生すると、数学関数は通常は 0.0 を返す (C99 では、指定された型において最小の正規化された正の値より大きくない 値を持つ実装定義 (implementation-defined) の値を返す、となっている)。 errno は ERANGE に設定され、「アンダーフロー」浮動小数点例外 (FE_UNDERFLOW) が上がる。
いくつかの関数では、渡された引数の値や、正しい関数の結果が subnormal (非正規化数) になる場合に範囲エラーを上げる。 subnormal な値とは、0 ではないが、その値が小さすぎて (仮数部の最上位ビットが 1 となる) 標準形では表現できないような値である。 subnormal な値の表現では、仮数部の上位側のビットに 1 個以上の 0 が 含まれることになる。
errno と fetestexcept(3) の両方を使ってエラーチェックを行うことで複雑になるのを避けるため、 多くの場合、関数呼び出しを行う前に不正な引数かのチェックを行う 方法が推奨されている。 例えば、以下のコードは、 log(3) の引数が NaN でも (極エラーとなる) 0 でも (領域エラーとなる) 0 未満 でもないことを保証するものである。
double x, r;
if (isnan(x) || islessequal(x, 0)) {
/* Deal with NaN / pole error / domain error */ }
r = log(x);
このページに書かれていることは、 (<complex.h> で宣言されている) 複素数関数にはあてはまらない。 一般に、C99 や POSIX.1 ではこれらの関数がエラーを返すことを 要求してない。
gcc(1) の -fno-math-errno オプションを使うと、実行ファイルで、標準の実装よりも高速な数学関数の 実装が使用されるようになるが、 エラー時に errno が設定されない (gcc(1) の -ffast-math オプションを指定した場合にも -fno-math-errno は有効になる)。 このオプションを指定した場合でも、 fetestexcept(3) を使ったエラーの検査は可能である。
[man1]
[man2]
[man3]
[man4]
[man5]
[man6]
[man7]
[man8]
[a]
[b]
[c]
[d]
[e]
[f]
[g]
[h]
[i]
[j]
[k]
[l]
[m]
[n]
[o]
[p]
[q]
[r]
[s]
[t]
[u]
[v]
[w]
[x]
[y]
[z]