目的
本記事の目的は筆者自身がPythonの四捨五入に躓き、学習と同時に作成している。
また、Pythonの四捨五入するための構文を控えておくための記事である。
Pythonの四捨五入はどのように記述すれば良いか
まずは結論としてPythonにおける四捨五入記述を下に記す。
decimalモジュールを使用して四捨五入を処理している。
from decimal import Decimal, ROUND_HALF_UP # 「import *」 でも可
a = 2.5
round_a = Decimal(a).quantize(Decimal('0'), rounding=ROUND_HALF_UP)
print(a, round_a)
2.5 3
from decimal import Decimal, ROUND_HALF_UP
b = 1.005
round_b = Decimal(b).quantize(Decimal('0.001'), rounding=ROUND_HALF_UP)
print(b, round_b)
1.005 1.01
ただし、上記四捨五入結果 round_a
, round_b
の型はdecimal.Decimal
となっているため、int型やfloat型と演算する際には注意が必要である。
その場合はfloat(round_A)
のように型の変換を組み込む必要がある。
Pythonのround関数は四捨五入ではない
四捨五入について
Pythonにて数値計算をする際、下記のようなround関数を使用したことがあるのではないだろうか
value1 = round(5.4, 0)
value2 = round(5.5, 0)
value3 = round(6.4, 0)
value4 = round(6.5, 0)
しかしながら、Pythonのround関数は俗に言う四捨五入と呼ばれる処理ではない。
偶数丸め(銀行丸め)と呼ばれる処理であるため、時には四捨五入を期待して実装したプログラムが意図しない挙動を起こす。
print(value1, value2, value3, value4)
# それぞれ 5.4, 5.5, 6.4, 6.5
5.0 6.0 6.0 6.0
上記の出力例では、5.4, 5.5, 6.4は問題なく四捨五入が行われているが、6.5については切り捨て処理が行われている。これは偶数丸めによって偶数になるように切り上げ、切り捨てが選択されているためである。
decimalモジュールについて
では、どのように記述すれば四捨五入が可能になるか。最もシンプルな方法は、decimalというモジュールを使用する方法と思われる。
decimalモジュールとは
decimalモジュールは十進数計算を正確に表現するために用いられるPythonの標準ライブラリの一種である。
コンピュータは2進数で計算を実行しているため、出入力の際は人が日常的に用いている10進数から変換、または10進数へ変換する必要がある。
10進数の浮動小数点型から2進数の浮動小数点型へ変換すると、基本的に無理数となってしまうため、正確に表現できないことが多い。そして、無理数を無理数のまま計算に用いることはできないため、ある程度で切った値を用いるが、この切った値を再び10進数に再変換するときにズレが生じる。
ズレ例:1.1 + 2.2 = 3.3000000000000003
10進数 | 2進数 | |
---|---|---|
1 | ⇒ | 0001 |
2 | ⇒ | 0010 |
3 | ⇒ | 0011 |
123 | ⇒ | 0111 1011 |
123.456 | ⇒ | 0111 1011.0111 0100… |
decimalモジュールはこのズレが発生しないように正確に計算するためのモジュールである。
decimalモジュールのメソッド
decimalモジュールのメソッドの一部を下に記す。
メソッド名 | 説明 |
---|---|
quantize() | 位を固定して数値を丸め込む。 |
getcontext() | 現在のDecimal型の演算環境設定を出力する。 |
setcontext() | 現在のDecimal型の演算環境設定を書き換える。 |
参考記事