Python decimalのgetcontext()とは?計算精度を設定する方法

getcontext()は、Decimalの計算設定(コンテキスト)を取得する関数です。

有効桁数や丸め方など、すべてのDecimal演算に共通する挙動をここで決めます。


現在の設定を見る

from decimal import getcontext

c = getcontext()

print("prec    :", c.prec)
print("rounding:", c.rounding)

実行結果:

prec    : 28
rounding: ROUND_HALF_EVEN

主な項目は次の2つです。

項目 既定値 意味
prec 28 有効桁数
rounding ROUND_HALF_EVEN 丸め方

precは「有効桁数」

ここを誤解しやすいので注意してください。precは小数点以下の桁数ではありません。

from decimal import Decimal, getcontext

getcontext().prec = 5

print(Decimal(1) / Decimal(3))
print(Decimal(12345) + Decimal(1))
print(Decimal(123456) + Decimal(1))

実行結果:

0.33333
12346
1.2346E+5

3行目に注目してください。整数の計算なのに指数表記になり、下の桁が失われています。

123457は6桁あり、prec=5に収まらないためです。

精度を絞ると、大きな整数の計算まで壊れます。安易に小さくしないでください。


precが効くタイミング

getcontext().prec = 3

print(Decimal('1.23456'))
print(Decimal('1.23456') + 0)

実行結果:

1.23456
1.23

作っただけでは丸まりません。演算した瞬間にprecが適用されます。

「値を保持するときは元のまま、計算結果は指定桁に丸める」という設計です。


影響範囲を限定する

from decimal import Decimal, localcontext

with localcontext() as ctx:
    ctx.prec = 3
    print("中:", Decimal(1) / Decimal(3))

print("外:", Decimal(1) / Decimal(3))

実行結果:

中: 0.333
外: 0.3333333333333333333333333333

getcontext()の変更はプログラム全体に効きます。ライブラリの内部処理まで巻き込みます。

一時的に変えたいだけならlocalcontext()を使ってください。withを抜けると自動で元に戻ります。


スレッドごとに独立している

import threading
from decimal import getcontext

def show():
    print("子スレッド:", getcontext().prec)

getcontext().prec = 7

t = threading.Thread(target=show)
t.start()
t.join()

print("親スレッド:", getcontext().prec)

実行結果:

子スレッド: 28
親スレッド: 7

設定は引き継がれません。各スレッドが自分のコンテキストを持ちます。

スレッドを使う処理では、ワーカーの中で設定し直す必要があります。これを忘れると、メインでは合っているのにワーカーの結果だけ違う、という事故になります。

「Python threadingとは?スレッド処理の基本を解説」も参照してください。


trapsでエラーの扱いを変える

from decimal import Decimal, DivisionByZero

Decimal(1) / Decimal(0)

実行結果:

decimal.DivisionByZero: [<class 'decimal.DivisionByZero'>]

既定ではゼロ除算が例外になります。これをInfinityを返す動作に変えられます。

from decimal import Decimal, localcontext, DivisionByZero

with localcontext() as ctx:
    ctx.traps[DivisionByZero] = False
    print(Decimal(1) / Decimal(0))

実行結果:

Infinity

実務では既定のまま(例外)にしておくほうが安全です。Infinityが紛れ込むと、どこで壊れたか追跡できなくなります。


触らないという選択

多くの場合、getcontext()を変更する必要はありません。

  • 桁をそろえたい → quantize()を使う
  • 四捨五入したい → rounding=ROUND_HALF_UPを都度指定
  • 金額計算 → 既定の28桁で十分

個別の演算で明示するほうが、読む人にとって分かりやすくなります。グローバル設定はどこで変えられたか追いにくいためです。

quantize()は「Python Decimalのquantize()とは?小数の桁を丸める方法」を参照してください。


getcontext()のまとめ

  • Decimal演算共通の設定を取得する
  • precは有効桁数——小数点以下の桁数ではない
  • 絞りすぎると大きな整数の計算まで壊れる
  • 適用されるのは演算した時点
  • 一時変更はlocalcontext()で
  • スレッド間で引き継がれない
  • 基本は触らず、quantize()で都度指定する

あわせて読みたい

対面・無料|東京・永田町で毎週開催

1回の参加で、プログラミングの構造がわかる

ゼロからはじめるPython入門講座

8年間・累計600回開催/これまで全国で2万人以上が参加

「やはり対面で聞けるのはとても気づきがあり、価値があると思います」

参加者の声

  • 本当に初心者からの講座です。プログラミングに触ったことがなくて大丈夫です
  • 対面だから、その場で聞けます。つまずいた所を持ち帰らずに解決できます
  • 講座は1時間。そのあとも残って学習を続けられ、講師にも質問できます
  • 独学で挫折した方も。糸口が見つかって、講座のあと会員になる方が多くいます

無料で参加する|開催日程を見る

参加費は無料です