コンテキスト (context) とは、算術演算における環境設定です。 コンテキストは計算精度を決定し、値丸めの方法を設定し、 シグナルのどれが例外になるかを決め、指数の範囲を制限しています。
多重スレッドで処理を行う場合には各スレッドごとに現在のコンテキストが あり、getcontext() や setcontext() といった関数で アクセスしたり設定変更できます:
) |
c) |
Python 2.5 から、with 文と localcontext() 関数を使っ て実行するコンテキストを一時的に変更することもできるようになりました。
[c]) |
たとえば、以下のコードでは精度を42桁に設定し、計算を実行し、そして 元のコンテキストに復帰します。
from __future__ import with_statement from decimal import localcontext with localcontext() as ctx: ctx.prec = 42 # 高精度の計算を実行 s = calculate_something() s = +s # 最終的な結果をデフォルトの精度に丸める
新たなコンテキストは、以下で説明するContext コンストラクタを 使って生成できます。その他にも、decimal モジュールでは 作成済みのコンテキストを提供しています:
多くのトラップが有効になっているので、デバッグの際に便利なコンテキスト です。
トラップが無効になっているので、エラーの伴う演算結果を NaN や Infinity にし、例外を送出しないようにしたいアプリケーションに 向いたコンテキストです。このコンテキストを使うと、他の場合にはプログラム が停止してしまうような状況があっても実行を完了させられます。
このコンテキストは、主に多重スレッド環境で便利です。スレッドを開始する 前に何らかのフィールドを変更しておくと、システム全体のデフォルト設定 に効果を及ぼせます。スレッドを開始した後にフィールドを変更すると 競合条件を抑制するためにスレッドを同期化せねばならないので推奨しません。
単一スレッドの環境では、このコンテキストを使わないよう薦めます。 下で述べるように明示的にコンテキストを作成してください。
デフォルトの値は精度 28 桁、丸め規則 ROUND_HALF_EVEN で、 トラップ Overflow、InvalidOperation、および DivisionByZero が有効になっています。
上に挙げた三つのコンテキストに加え、Context コンストラクタを 使って新たなコンテキストを生成できます。
prec=None, rounding=None, traps=None, flags=None, Emin=None, Emax=None, capitals=1) |
prec フィールドは正の整数で、コンテキストにおける算術演算の 計算精度を設定します。
rounding は、
traps および flags フィールドには、セットしたい シグナルを列挙します。一般的に、新たなコンテキストを作成するときには トラップだけを設定し、フラグはクリアしておきます。
Emin および Emax フィールドには、指数範囲の外側値を整数で 指定します。
capitals フィールドは 0 または 1 (デフォルト) にします。1 に設定すると、指数記号を大文字 E で 出力します。それ以外の場合には Decimal('6.02e+23') のようにe を使います。
Context クラスでは、いくつかの汎用のメソッドの他、現在の コンテキストで算術演算を直接行うためのメソッドを数多く定義しています。
) |
) |
num) |
定数値はしばしばアプリケーションの要求よりも高い精度を持っているため、 このメソッドが役に立ちます。また、値丸めを即座に行うため、 例えば以下のように、入力値に値丸めを行わないために合計値にゼロの加算を 追加するだけで結果が変わってしまうといった、現在の精度 よりも細かい値の影響が紛れ込む問題を防げるという恩恵もあります。
>>> getcontext().prec = 3 >>> Decimal("3.4445") + Decimal("1.0023") Decimal("4.45") >>> Decimal("3.4445") + Decimal(0) + Decimal("1.0023") Decimal("4.44")
) |
) |
Decimal を使った処理を行う場合、通常は Decimal インスタンスを生成して、算術演算を適用するというアプローチを とります。演算はアクティブなスレッドにおける現在のコンテキストの 下で行われます。もう一つのアプローチは、コンテキストのメソッドを 使った特定のコンテキスト下での計算です。 コンテキストのメソッドは Decimal クラスのメソッドに似ているので、 ここでは簡単な説明にとどめます。
x) |
x, y) |
x, y) |
__cmp__() に似ていますが、 以下のようにDecimal インスタンスを返します:
a or b is a NaN ==> Decimal("NaN") a < b ==> Decimal("-1") a == b ==> Decimal("0") a > b ==> Decimal("1")
x, y) |
x, y) |
x, y) |
数値上二つの値が等しい場合には、左側値を結果として返します。
x, y) |
数値上二つの値が等しい場合には、左側値を結果として返します。
x) |
x, y) |
x) |
本質的には、plus 演算の結果から末尾のゼロを全て取り除いた ものと同じです。
x) |
x, y[, modulo]) |
右被演算子は整数部が 9 桁以下で、小数部 (のある場合) は値丸め前に 全てゼロになっていなければなりません。被演算子は正でも負でもゼロでも かまいません。右被演算子が負の場合には、左被演算子の逆数 (1 を左被演算子で割った値) を右被演算子の逆数でべき乗します。
中間演算でより高い計算精度が必要になり、その精度が実装の提供している 精度を超えた場合、InvalidOperation エラーをシグナルします。
負のべき乗を行う際に 1 への除算でアンダーフローが起きても、 その時点では演算を停止せず継続します。
x, y) |
他の演算と違い、量子化後の係数の長さが精度よりも大きい場合には InvalidOperation をシグナルします。 このため、エラーが生じないかぎり、量子化後の指数は右側の被演算子 の指数と等しくなることが保証されます。
また、結果が劣化していたり不正確な値であっても、Underflow をシグナルしないという点も他の演算と異なります。
x, y) |
剰余がゼロでない場合、符号は割られる数の符号と同じになります。
x, y) |
Decimal("4")
よりもゼロに近い値 Decimal("-2")
を返します。
ゼロからの差が同じ場合には、 self と同じ符号を持った方を 返します。
x, y) |
x) |
x, y) |
) |
工学表記では指数は 3 の倍数になります。従って、
最大で 3 桁までの数字が基数の小数部に現れます。たとえば、
Decimal('123E+1')
は Decimal("1.23E+3")
に変換されます。
x) |
x) |
ご意見やご指摘をお寄せになりたい方は、 このドキュメントについて... をご覧ください。