例外を定義することは困難です。W. Kahan 氏によると、
算術演算例外は、試行された不可分な算術演算が、一般に受け入れられるような結果にならなかったときに発生します。不可分と許容の意味は、時間と場所によって異なります。(『Handling Arithmetic Exceptions』、W. Kahan 著を参照してください)。
たとえば、プログラムで負の数の平方根を求めようとすると例外が発生します。この例は、無効な演算例外の一例です。そのような例外が発生した場合、システムは 2 つの方法のいずれかで対応します。
例外のトラップが無効である場合 (デフォルト) は、例外が発生したことがシステムに記録され、IEEE 754 で指定されている例外演算に関するデフォルトの結果を使用して、プログラムの実行が続行されます。
例外のトラップが有効である場合は、SIGFPE シグナルが生成されます。プログラムに SIGFPE シグナルハンドラがインストールされている場合は、そのシグナルハンドラに制御が移ります。シグナルハンドラが設定されていない場合は、プログラムが中止されます。
IEEE 754 は、5 種類の 基本的な浮動小数点例外 (無効な演算、0 による除算、オーバーフロー、アンダーフロー、および不正確) を定義しています。最初の 3 つ (無効な演算、0 による除算、およびオーバーフロー) は、一般的な例外と呼ばれることがあります。通常、これらの例外が発生した場合は無視できません。 ieee_handler(3m) のマニュアルページには、一般的な例外のみをトラップする簡単な方法が説明されています。ほかの 2 つの例外 (アンダーフローと不正確) はより頻繁に確認されます。実際、ほとんどの浮動小数点演算で不正確例外が発生しています。これらの例外は、通常、常にとは言えませんが、安全に無視できます。Oracle Developer Studio 12.5 C、C++、および f77 コンパイラは、デフォルトですべての IEEE トラップを無効にします。f95 コンパイラは、デフォルトで一般的な例外に対してトラップを有効にします。f95 –ftrap=none を指定してコンパイルすると、754 標準に準拠するようになります。
表 31 は、IEEE 規格 754 の情報を要約しています。5 つの浮動小数点例外、およびそれらの例外が発生したときの IEEE 演算環境のデフォルトの応答を示しています。
|
非順序付け比較: 任意の浮動小数値のペアは、形式が異なっていても比較できます。次の 4 つの相互に排他的な関係 (より小さい、より大きい、等しい、または非順序付け) があります。非順序付けとは、オペランドのうち少なくとも 1 つが NaN (非数) であることを意味します。
それぞれの NaN は、その NaN 自体も含めてすべての値に対して「非順序付け」で比較されます。次の表は、関係が非順序付けのときに、無効な演算例外を発生する述語を示しています。
|
無効な変換: NaN、または無限大から整数に変換しようとすること、あるいは浮動小数点形式からの変換時に発生した整数値オーバーフロー。
IEEE の単精度、倍精度、および拡張倍精度の形式で表現可能な最小の正規数は、それぞれ 2-126、2-1022、および 2-16382 です。IEEE の浮動小数点形式については、IEEE 演算を参照してください。
次の表は、オーバーフローに対するトラップが無効にされているときのデフォルトの結果を一覧表示しています。これらの結果は、丸めモードおよび中間結果の符号によって異なります。
|
x86 浮動小数点環境には、IEEE 規格にはない例外である非正規オペランド例外があります。この例外は、浮動小数点演算が非正規数に対して実行された場合に発生します。
例外は、 次の順序で優先付けされます。無効 (もっとも高い優先度)、オーバーフロー、除算、アンダーフロー、不正確 (もっとも低い優先度)。x86 ベースのシステムでは、非正規オペランド例外はもっとも低い優先度になります。
単一の演算で同時に発生する可能性のある標準例外の組み合わせは、オーバーフローと不正確、およびアンダーフローと不正確のみです。x86 ベースのシステムでは、非正規オペランド例外は 5 つの標準例外のいずれかとともに発生することがあります。 オーバーフロー、アンダーフロー、および不正確のトラップが有効になっている場合は、オーバーフローとアンダーフローのトラップが不正確のトラップよりも優先されます。これらはすべて、x86 ベースのシステムで非正規オペランドのトラップよりも優先されます。