Pythonでのdecimalモジュールの扱い方とは?演算誤差を防ぐためのdecimal

エンジニア
マネージャー
Pythonでのdecimalモジュールの扱い方とは?
今回は、Pythonでのdecimalモジュールの扱い方について説明します。
小数点を扱う場合、float型を使用します。
コンピュータは2進数で数値を扱うため、誤差が発生する場合があります。
これを防ぐために、Pythonではdecimalモジュールが用意されています。
ここでは、decimalモジュールの
・基本的な使い方
・演算
・FloatOperationのtrap
・精度の指定
・四捨五入(round)
・四捨五入(quantize)
について紹介します。
Pythonでのdecimalモジュールの扱い方に興味のある方はぜひご覧ください。
基本的な使い方
Pythonでのdecimalモジュールの基本的な使い方を紹介します。
decimalモジュールを使用するにはimportが必要です。
1 |
from decimal import Decimal |
実際のソースコードを見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
from decimal import Decimal # floatの計算 f1 = 0.1 f2 = 0.2 f3 = f1 + f2 # decimalの計算 d1 = Decimal("0.1") d2 = Decimal("0.2") d3 = d1 + d2 print(f3) # 0.30000000000000004 print(d3) # 0.3 print(f3 == d3) # False |
実行結果は以下のようになります。
1 2 3 |
0.30000000000000004 0.3 False |
float型で計算した場合は、誤差が生じています。
一方、decimalモジュールで計算した場合、誤差が生じていません。
Decimalクラスには、文字列を指定する必要があります。
このようにdecimalモジュールを使用します。
演算
Pythonでのdecimalモジュールを使った演算について紹介します。
実際のソースコードを見てみましょう。
1 2 3 4 5 6 7 8 9 |
from decimal import Decimal d1 = Decimal("0.1") d2 = Decimal("0.2") print(d1 + d2) # 0.3 print(d1 - d2) # -0.1 print(d1 * d2) # 0.02 print(d1 / d2) # 0.5 |
実行結果は以下のようになります。
1 2 3 4 |
0.3 -0.1 0.02 0.5 |
このように、誤差なく加減乗除の演算ができます。
FloatOperationのtrap
Decimalクラスには、文字列を指定する必要があります。
数値を指定してもエラーにはなりません。
演算結果はどのようになるのでしょうか。
実際のソースコードを見てみましょう。
1 2 3 4 5 6 |
from decimal import Decimal d1 = Decimal(0.1) d2 = Decimal(0.2) print(d1 + d2) # 0.3000000000000000166533453694 |
実行結果は以下のようになります。
1 |
0.3000000000000000166533453694 |
数値で指定すると、誤差が生じていることが分かります。
間違って数値で指定することを防ぐために、FloatOperationのtrapを有効にする方法があります。
実際のソースコードを見てみましょう。
1 2 3 4 5 6 7 8 9 |
from decimal import Decimal, getcontext, FloatOperation # FloatOperationのtrapを有効にする getcontext().traps[FloatOperation] = True # float初期化で実行時エラー d1 = Decimal(0.1) # floatの演算で実行時エラー d2 = Decimal(2) * 0.5 |
実行結果は以下のようになります。
1 2 3 4 |
Traceback (most recent call last): File "Main.py", line 7, in <module> d1 = Decimal(0.1) decimal.FloatOperation: [<class 'decimal.FloatOperation'>] |
Decimalをfloatで初期化したり、Decimalをfloatで計算すると、実行時エラーが発生します。
このように、PythonではFloatOperationのtrapを有効にすることで、意図しない初期化や演算を防げます。
精度の指定
Pythonでのdecimalモジュールを使った、精度を指定した演算について紹介します。
実際のソースコードを見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 |
from decimal import Decimal, getcontext # 文字列ではなく、floatを指定 d1 = Decimal(0.1) d2 = Decimal(0.2) print(d1 + d2) # 0.3000000000000000166533453694 # 精度の指定 getcontext().prec = 5 print(d1 + d2) # 0.30000 |
実行結果は以下のようになります。
1 2 |
0.3000000000000000166533453694 0.30000 |
「getcontext().prec」で精度を指定することで、演算結果が指定精度で出力されていることが分かります。
このように、Pythonでは精度を指定した演算ができます。
四捨五入(round)
Pythonでのdecimalモジュールを使った丸めについて紹介します。
組み込み関数のroundメソッドを使用します。
実際のソースコードを見てみましょう。
1 2 3 4 5 6 7 8 9 |
f = 123.456 print(round(f)) # 123 print(round(f, 1)) # 123.5 print(round(f, 2)) # 123.46 print(round(f, 3)) # 123.456 print(round(f, 0)) # 123.0 print(round(f, -1)) # 120.0 print(round(f, -2)) # 100.0 |
実行結果は以下のようになります。
1 2 3 4 5 6 7 |
123 123.5 123.46 123.456 123.0 120.0 100.0 |
小数を任意の桁数で四捨五入したり、整数を任意の桁数で四捨五入したりできます。
このように、組み込み関数のroundメソッドで四捨五入できます。
四捨五入(quantize)
Pythonでのdecimalモジュールを使った丸めについて、もう一つの方法を紹介します。
decimal標準ライブラリのquantizeメソッドを使用します。
実際のソースコードを見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
from decimal import * d1 = Decimal("123.456") print(d1.quantize(Decimal("0"),rounding=ROUND_HALF_UP)) # 123 # 小数部の四捨五入 print(d1.quantize(Decimal("0.1"),rounding=ROUND_HALF_UP)) # 123.5 print(d1.quantize(Decimal("0.01"),rounding=ROUND_HALF_UP)) # 123.46 print(d1.quantize(Decimal("0.001"),rounding=ROUND_HALF_UP)) # 123.456 # 整数部の四捨五入 print(d1.quantize(Decimal("1E1"),rounding=ROUND_HALF_UP)) # 1.2E+2 print(d1.quantize(Decimal("1E2"),rounding=ROUND_HALF_UP)) # 1E+2 print(d1.quantize(Decimal("1E3"),rounding=ROUND_HALF_UP)) # 0E+3 # 整数部の四捨五入(intにして見やすく) print(int(d1.quantize(Decimal("1E1"),rounding=ROUND_HALF_UP))) # 120 print(int(d1.quantize(Decimal("1E2"),rounding=ROUND_HALF_UP))) # 100 print(int(d1.quantize(Decimal("1E3"),rounding=ROUND_HALF_UP))) # 0 |
実行結果は以下のようになります。
1 2 3 4 5 6 7 8 9 10 |
123 123.5 123.46 123.456 1.2E+2 1E+2 0E+3 120 100 0 |
整数部の四捨五入は少し特殊です。
このように、Pythonではquantizeメソッドで四捨五入できます。
エンジニア
マネージャー
まとめ
Pythonでのdecimalモジュールの扱い方について説明しました。
基本的な使い方だけでなく、演算精度の指定方法や四捨五入の方法なども紹介しました。
ぜひご自身でソースコードを書いて、理解を深めてください。
FEnet.NETナビ・.NETコラムは株式会社オープンアップシステムが運営しています。
株式会社オープンアップシステムはこんな会社です
秋葉原オフィスには株式会社オープンアップシステムをはじめグループのIT企業が集結!
数多くのエンジニアが集まります。

-
スマホアプリから業務系システムまで
スマホアプリから業務系システムまで開発案件多数。システムエンジニア・プログラマーとしての多彩なキャリアパスがあります。
-
充実した研修制度
毎年、IT技術のトレンドや社員の要望に合わせて、カリキュラムを刷新し展開しています。社内講師の丁寧なサポートを受けながら、自分のペースで学ぶことができます。
-
資格取得を応援
スキルアップしたい社員を応援するために資格取得一時金制度を設けています。受験料(実費)と合わせて資格レベルに合わせた最大10万円の一時金も支給しています。
-
東証プライム上場企業グループ
オープンアップシステムは東証プライム上場「株式会社オープンアップグループ」のグループ企業です。
安定した経営基盤とグループ間のスムーズな連携でコロナ禍でも安定した雇用を実現させています。
株式会社オープンアップシステムに興味を持った方へ
株式会社オープンアップシステムでは、開発系エンジニア・プログラマを募集しています。
年収をアップしたい!スキルアップしたい!大手の上流案件にチャレンジしたい!
まずは話だけでも聞いてみたい場合もOK。お気軽にご登録ください。


新着案件New Job
開発エンジニア/東京都品川区/【WEB面談可】/在宅ワーク
月給29万~30万円東京都品川区(大崎駅)遠隔テストサービス機能改修/JavaScript/東京都港区/【WEB面談可】/テレワーク
月給45万~60万円東京都港区(六本木駅)病院内システムの不具合対応、保守/東京都豊島区/【WEB面談可】/テレワーク
月給30万~30万円東京都豊島区(池袋駅)開発/JavaScript/東京都豊島区/【WEB面談可】/テレワーク
月給50万~50万円東京都豊島区(大塚駅)債権債務システム追加開発/東京都文京区/【WEB面談可】/在宅勤務
月給62万~67万円東京都文京区(後楽園駅)PMO/東京都豊島区/【WEB面談可】/在宅勤務
月給55万~55万円東京都豊島区(池袋駅)