MATH_ERROR
Section: Linux Programmer's Manual (7)
Updated: 2008-08-11
Index
JM Home Page
roff page
名前
math_error - 数学関数からのエラーの検出
書式
#include <math.h>
#include <errno.h>
#include <fenv.h>
説明
エラーが発生すると、ほとんどのライブラリ関数は (-1 や NULL などの)
特別な値を返すことでエラーを通知する。
<math.h>
で宣言されている数学関数は、通常は浮動小数点値を返すので、
他の機構を使ってエラーを通知する。
エラー通知機構は 2 種類あり、
古いものが
errno
を設定するやり方であり、新しいものが
fenv(3)
で説明されている浮動小数点例外機構である。
(feclearexcept(3)
と
fetestexcept(3)
を使用する。これらについては以下で概要を説明している。)
移植性が必要なプログラムで、数学関数からのエラーを確認する必要がある場合には、
数学関数を呼び出す前に
errno
を 0 に設定し、以下を呼び出すべきである。
feclearexcept(FE_ALL_EXCEPT);
数学関数から返ってきた際に、
errno
が 0 以外か、以下の呼び出しが 0 以外を返した場合
(fenv(3)
参照)、数学関数でエラーが発生している。
fetestexcept(FE_INVALID | FE_DIVBYZERO | FE_OVERFLOW |
FE_UNDERFLOW);
数学関数で発生するエラー条件については以下で説明する。
領域エラー (domain error)
領域エラー
が発生するのは、数学関数に渡された引き数の値がその関数が定義されている
領域に入っていない場合である (例えば
log(3)
に負の引き数を渡した場合)。
領域エラーが発生すると、
数学関数は普通は NaN を返し
(同じ状況で違う値を返す関数もある)、
errno
に
EDOM
を設定し、「無効 (invalid)」
浮動小数点例外
(FE_INVALID)
を上げる。
極エラー (pole error)
極エラー
が発生するのは、関数の数学的な結果が無限大そのものとなる場合である
(例えば
0 の対数は負の無限大である)。
極エラーが発生すると、その関数の返り値は (符号付きの)
HUGE_VAL,
HUGE_VALF,
HUGE_VALL
のいずれかとなる (前記の値のうちどれが返るかは関数の返り値の型により決まり、
それぞれ
double,
float,
long double
に対応する)。
結果の符号は、その関数の数学的な定義から決定される。
errno
は
ERANGE
に設定され、「0 による除算 (divide-by-zero)」
浮動小数点例外
(FE_DIVBYZERO)
が上がる。
範囲エラー (range エラー)
範囲エラー
が発生するのは、関数の結果の値がその関数の返り値の型では表現できない場合
である。関数の返り値は、範囲エラーがオーバーフローであったかアンダーフロー
であったかによって異なる。
浮動小数点のオーバーフローは、結果が有限だが、大き過ぎて
結果を返す型では表現できない場合に発生する。
オーバーフローが発生すると、
その関数は
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 が
含まれることになる。
注意
C99 と POSIX.1-2001 で規定されている
math_errhandling
識別子は glibc ではサポートされていない。
この識別子は、2 つのエラー通知機構
(errno
と
fetestexcept(3)
経由で取得できる例外) のうちどちらが使用されているかを通知
することになっている。
標準では、少なくとも一つは使用されることが要求されているが、
両方とも利用可能であってもよいとされている。
glibc での現在の (バージョン 2.8 での) 状況はかなり混乱している。
ほとんどの関数 (ただし全部ではない) はエラー時に例外を上げる。
いくつかの関数は
errno
も設定する。
errno
を設定するが、例外を上げない関数も少しだけ存在する。
どちらも行わない関数もごく少数だが存在する。
詳細については個々のマニュアルページを参照のこと。
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-2001 ではこれらの関数がエラーを返すことを
要求してない。
gcc(1)
の
-fno-math-errno
オプションを使うと、実行ファイルで、標準の実装よりも高速な数学関数の
実装が使用されるようになるが、
エラー時に
errno
が設定されない
(gcc(1)
の
-ffast-math
オプションを指定した場合にも
-fno-math-errno
は有効になる)。
このオプションを指定した場合でも、
fetestexcept(3)
を使ったエラーの検査は可能である。
関連項目
gcc(1),
errno(3),
fenv(3),
fpclassify(3),
INFINITY(3),
isgreater(3),
matherr(3),
nan(3)
info libc
Index
- 名前
-
- 書式
-
- 説明
-
- 領域エラー (domain error)
-
- 極エラー (pole error)
-
- 範囲エラー (range エラー)
-
- 注意
-
- 関連項目
-
This document was created by
man2html,
using the manual pages.
Time: 03:26:48 GMT, April 25, 2010