##
3 Context オブジェクト

コンテキスト (context) とは、算術演算における環境設定です。 コンテキストは計算精度を決定し、値丸めの方法を設定し、 シグナルのどれが例外になるかを決め、指数の範囲を制限しています。

多重スレッドで処理を行う場合には各スレッドごとに現在のコンテキストが あり、`getcontext()` や `setcontext()` といった関数で アクセスしたり設定変更できます:

`getcontext`( | )

  アクティブなスレッドの現在のコンテキストを返します。

`setcontext`( | c)

  アクティブなスレッドのコンテキストを c に設定します。

Python 2.5 から、`with` 文と `localcontext()` 関数を使っ て実行するコンテキストを一時的に変更することもできるようになりました。

`localcontext`( | [c])

  with 文の入口でアクティブなスレッドのコンテキストを c のコピー に設定し、with 文を抜ける時に元のコンテキストに復旧する、コンテキスト マネージャを返します。コンテキストが指定されなければ、現在のコンテキ ストのコピーが使われます。 バージョン 2.5 で 新たに追加 された仕様です。

  たとえば、以下のコードでは精度を42桁に設定し、計算を実行し、そして 元のコンテキストに復帰します。

          from __future__ import with_statement
          from decimal import localcontext

          with localcontext() as ctx:
              ctx.prec = 42   # 高精度の計算を実行
              s = calculate_something()
          s = +s  # 最終的な結果をデフォルトの精度に丸める

新たなコンテキストは、以下で説明する`Context` コンストラクタを 使って生成できます。その他にも、`decimal` モジュールでは 作成済みのコンテキストを提供しています:

class `BasicContext`
  General Decimal Arithmetic Specification で定義されている標準コンテキスト の一つです。精度は 9 桁に設定されています。丸め規則は `ROUND_HALF_UP` です。すべての演算結果フラグはクリアされています。`Inexact`、 `Rounded`、`Subnormal` を除く全ての演算エラートラップが 有効 (例外として扱う) になっています。

  多くのトラップが有効になっているので、デバッグの際に便利なコンテキスト です。

class `ExtendedContext`
  General Decimal Arithmetic Specification で定義されている標準コンテキスト の一つです。精度は 9 桁に設定されています。丸め規則は `ROUND_HALF_EVEN` です。すべての演算結果フラグはクリアされています。 トラップは全て無効 (演算中に一切例外を送出しない) になっています。

  トラップが無効になっているので、エラーの伴う演算結果を `NaN` や `Infinity` にし、例外を送出しないようにしたいアプリケーションに 向いたコンテキストです。このコンテキストを使うと、他の場合にはプログラム が停止してしまうような状況があっても実行を完了させられます。

class `DefaultContext`
  `Context` コンストラクタが新たなコンテキストを作成するさいに 雛形にするコンテキストです。このコンテキストのフィールド (精度の設定など) を変更すると、`Context` コンストラクタが生成する新たなコンテキストに 影響を及ぼします。

  このコンテキストは、主に多重スレッド環境で便利です。スレッドを開始する 前に何らかのフィールドを変更しておくと、システム全体のデフォルト設定 に効果を及ぼせます。スレッドを開始した後にフィールドを変更すると 競合条件を抑制するためにスレッドを同期化せねばならないので推奨しません。

  単一スレッドの環境では、このコンテキストを使わないよう薦めます。 下で述べるように明示的にコンテキストを作成してください。

  デフォルトの値は精度 28 桁、丸め規則 `ROUND_HALF_EVEN` で、 トラップ `Overflow`、`InvalidOperation`、および `DivisionByZero` が有効になっています。

上に挙げた三つのコンテキストに加え、`Context` コンストラクタを 使って新たなコンテキストを生成できます。

クラス `Context`( | prec=None, rounding=None, traps=None, flags=None, Emin=None, Emax=None, capitals=1)

  新たなコンテキストを生成します。あるフィールドが定義されていないか `None` であれば、 `DefaultContext` からデフォルト値を コピーします。 flags フィールドが設定されていいか `None` の場合には、全てのフラグがクリアされます。

  prec フィールドは正の整数で、コンテキストにおける算術演算の 計算精度を設定します。

  rounding は、

  - `ROUND_CEILING` (`Infinity` 寄りの値にする),
  - `ROUND_DOWN` (ゼロ寄りの値にする),
  - `ROUND_FLOOR` (`-Infinity` 寄りの値にする),
  - `ROUND_HALF_DOWN` (最近値のうちゼロ寄りの値にする),
  - `ROUND_HALF_EVEN` (最近値のうち偶数値を優先する),
  - `ROUND_HALF_UP` (最近値のうちゼロから遠い値にする), または
  - `ROUND_UP` (ゼロから遠い値にする)
  のいずれかです。

  traps および flags フィールドには、セットしたい シグナルを列挙します。一般的に、新たなコンテキストを作成するときには トラップだけを設定し、フラグはクリアしておきます。

  Emin および Emax フィールドには、指数範囲の外側値を整数で 指定します。

  capitals フィールドは `0` または `1` (デフォルト) にします。`1` に設定すると、指数記号を大文字 `E` で 出力します。それ以外の場合には `Decimal('6.02e+23')` のように`e` を使います。

`Context` クラスでは、いくつかの汎用のメソッドの他、現在の コンテキストで算術演算を直接行うためのメソッドを数多く定義しています。

`clear_flags`( | )

  フラグを全て `0` にリセットします。

`copy`( | )

  コンテキストの複製を返します。

`create_decimal`( | num)

  self をコンテキストとする新たな Decimal インスタンスを num から生成します。`Decimal` コンストラクタと違い、 数値を変換する際にコンテキストの精度、値丸め方法、フラグ、トラップ を適用します。

  定数値はしばしばアプリケーションの要求よりも高い精度を持っているため、 このメソッドが役に立ちます。また、値丸めを即座に行うため、 例えば以下のように、入力値に値丸めを行わないために合計値にゼロの加算を 追加するだけで結果が変わってしまうといった、現在の精度 よりも細かい値の影響が紛れ込む問題を防げるという恩恵もあります。

          >>> getcontext().prec = 3
          >>> Decimal("3.4445") + Decimal("1.0023")
          Decimal("4.45")
          >>> Decimal("3.4445") + Decimal(0) + Decimal("1.0023")
          Decimal("4.44")

`Etiny`( | )

  "`Emmin - prec + 1`" に等しい値を返します。 演算結果の劣化が起こる桁の最小値です。アンダーフローが起きた場合、 指数は `Etiny` に設定されます。

`Etop`( | )

  "`Emax - prec + 1`" に等しい値を返します。

`Decimal` を使った処理を行う場合、通常は `Decimal` インスタンスを生成して、算術演算を適用するというアプローチを とります。演算はアクティブなスレッドにおける現在のコンテキストの 下で行われます。もう一つのアプローチは、コンテキストのメソッドを 使った特定のコンテキスト下での計算です。 コンテキストのメソッドは `Decimal` クラスのメソッドに似ているので、 ここでは簡単な説明にとどめます。

`abs`( | x)

  x の絶対値を返します。

`add`( | x, y)

  x と y の加算を返します。

`compare`( | x, y)

  二つの値を数値として比較します。

  `__cmp__()` に似ていますが、 以下のように`Decimal` インスタンスを返します:

              a or b is a NaN ==> Decimal("NaN")
              a < b           ==> Decimal("-1")
              a == b          ==> Decimal("0")
              a > b           ==> Decimal("1")

`divide`( | x, y)

  x を y で除算した値を返します。

`divmod`( | x, y)

  二つの数値間の除算を行い、結果の整数部を返します。

`max`( | x, y)

  二つの値を数値として比較し、大きいほうを返します。

  数値上二つの値が等しい場合には、左側値を結果として返します。

`min`( | x, y)

  二つの値を数値として比較し、小さいほうを返します。

  数値上二つの値が等しい場合には、左側値を結果として返します。

`minus`( | x)

  Python における単項の符号反転前置演算子 (unary prefix minus operator) に対応する演算です。

`multiply`( | x, y)

  x とy の積を返します。

`normalize`( | x)

  被演算子をもっとも単純な表記にします。

  本質的には、`plus` 演算の結果から末尾のゼロを全て取り除いた ものと同じです。

`plus`( | x)

  Python における単項の符号非反転前置演算子 (unary prefix plus operator) に対応する演算です。コンテキストにおける精度や値丸めを適用する ので、等値 (identity) 演算とは 違います。

`power`( | x, y[, modulo])

  "`x ** y`" を計算します。modulo が指定されていれば使います。

  右被演算子は整数部が 9 桁以下で、小数部 (のある場合) は値丸め前に 全てゼロになっていなければなりません。被演算子は正でも負でもゼロでも かまいません。右被演算子が負の場合には、左被演算子の逆数 (1 を左被演算子で割った値) を右被演算子の逆数でべき乗します。

  中間演算でより高い計算精度が必要になり、その精度が実装の提供している 精度を超えた場合、`InvalidOperation` エラーをシグナルします。

  負のべき乗を行う際に 1 への除算でアンダーフローが起きても、 その時点では演算を停止せず継続します。

`quantize`( | x, y)

  x に値丸めを適用し、指数を y にした値を返します。

  他の演算と違い、量子化後の係数の長さが精度よりも大きい場合には `InvalidOperation` をシグナルします。 このため、エラーが生じないかぎり、量子化後の指数は右側の被演算子 の指数と等しくなることが保証されます。

  また、結果が劣化していたり不正確な値であっても、`Underflow` をシグナルしないという点も他の演算と異なります。

`remainder`( | x, y)

  整数除算の剰余を返します。

  剰余がゼロでない場合、符号は割られる数の符号と同じになります。

`remainder_near`( | x, y)

  モジュロを計算し、正負のモジュロのうちゼロに近い値を返します。 たとえば、 "`Decimal(10).remainder_near(6)`" は `Decimal("4")` よりもゼロに近い値 `Decimal("-2")` を返します。

  ゼロからの差が同じ場合には、 self と同じ符号を持った方を 返します。

`same_quantum`( | x, y)

  self と other が同じ指数を持っているか、あるいは 双方とも `NaN` である場合に真を返します。

`sqrt`( | x)

  x の平方根を精度いっぱいまで求めます。

`subtract`( | x, y)

  x とy の間の差を返します。

`to_eng_string`( | )

  工学表記で文字列に変換します。

  工学表記では指数は 3 の倍数になります。従って、 最大で 3 桁までの数字が基数の小数部に現れます。たとえば、 `Decimal('123E+1')` は `Decimal("1.23E+3")` に変換されます。

`to_integral`( | x)

  `Inexact` や `Rounded` といったシグナルを出さずに 最近傍の整数に値を丸めます。

`to_sci_string`( | x)

  数値を科学表記で文字列に変換します。