# 28.16. `fpectl` --- 浮動小数点例外の制御

注釈

`fpectl` モジュールはデフォルトではビルドされません。このモジュールの利用は推奨されておらず、熟練者以外がこのモジュールを使うのは危険です。このモジュールの制限についての詳細は、 制限と他に考慮すべきこと 節を参照してください。

ほとんどのコンピュータはいわゆるIEEE-754標準に準拠した浮動小数点演算を実行します。実際のどんなコンピュータでも、浮動小数点演算が普通の浮動小数点数では表せない結果になることがあります。例えば、次を試してください

    >>> import math
    >>> math.exp(1000)
    inf
    >>> math.exp(1000) / math.exp(1000)
    nan

(上の例は多くのプラットホームで動作します。DEC Alphaは例外かもしれません。) "Inf"は"infinity(無限)"を意味するIEEE-754における特殊な非数値の値で、"nan"は"not a number(数ではない)"を意味します。ここで留意すべき点は、その計算を行うようにPythonに求めたときに非数値の結果以外に特別なことは何も起きないというです。事実、それはIEEE-754標準に規定されたデフォルトのふるまいで、それで良ければここで読むのを止めてください。

いくつかの環境では、誤った演算がなされたところで例外を発生し、処理を止めることがより良いでしょう。 `fpectl` モジュールはそんな状況で使うためのものです。いくつかのハードウェア製造メーカーの浮動小数点ユニットを制御できるようにします。つまり、IEEE-754例外Division by Zero、OverflowあるいはInvalid Operationが起きたときはいつでも `SIGFPE` が生成させるように、ユーザが切り替えられるようにします。あなたのpythonシステムを構成しているCコードの中へ挿入される一組のラッパーマクロと協力して、 `SIGFPE` は捕捉され、Python `FloatingPointError` 例外へ変換されます。

`fpectl` モジュールは次の関数を定義しています。また、所定の例外を発生します:

`fpectl.``turnon_sigfpe`()

  `SIGFPE` を生成するように切り替え、適切なシグナルハンドラを設定します。

`fpectl.``turnoff_sigfpe`()

  浮動小数点例外のデフォルトの処理に再設定します。

exception `fpectl.``FloatingPointError`

  `turnon_sigfpe()` が実行された後に、IEEE-754例外であるDivision by Zero、OverflowまたはInvalid operationの一つを発生する浮動小数点演算は、次にこの標準Python例外を発生します。

## 28.16.1. 例

以下の例は `fpectl` モジュールの使用を開始する方法とモジュールのテスト演算について示しています。

    >>> import fpectl
    >>> import fpetest
    >>> fpectl.turnon_sigfpe()
    >>> fpetest.test()
    overflow        PASS
    FloatingPointError: Overflow

    div by 0        PASS
    FloatingPointError: Division by zero
      [ more output from test elided ]
    >>> import math
    >>> math.exp(1000)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    FloatingPointError: in math_1

## 28.16.2. 制限と他に考慮すべきこと

特定のプロセッサをIEEE-754浮動小数点エラーを捕らえるように設定することは、現在アーキテクチャごとの基準に基づきカスタムコードを必要とします。あなたの特殊なハードウェアを制御するために `fpectl` を修正することもできます。

IEEE-754例外のPython例外への変換には、ラッパーマクロ `PyFPE_START_PROTECT` と `PyFPE_END_PROTECT` があなたのコードに適切な方法で挿入されていることが必要です。Python自身は `fpectl` モジュールをサポートするために修正されていますが、数値解析にとって興味ある多くの他のコードはそうではありません。

`fpectl` モジュールはスレッドセーフではありません。

参考

このモジュールがどのように動作するのかについてより学習するときに、ソースディストリビューションの中のいくつかのファイルは興味を引くものでしょう。インクルードファイル `Include/pyfpe.h` では、このモジュールの実装について同じ長さで議論されています。 `Modules/fpetestmodule.c` には、いくつかの使い方の例があります。多くの追加の例が `Objects/floatobject.c` にあります。