Python

ちょっと注意!!Pythonで四捨五入、切り上げ、切り捨てをするには?

ちょっと注意!!Pythonで四捨五入、切り上げ、切り捨てをするには?
Androidスマホを自動化しようとあれこれやっていたら、四捨五入をしたくなりました。
調べてみると、Pythonでの四捨五入にはちょっと注意が要るそうです。
合わせて、切り上げや切り捨てについてもまとめておきます。

 

四捨五入するには?

「Decimal.quantize()」を使います。
まずは、標準ライブラリ「decimal」をインポートします。
それの「quantize()」に2つの引数を指定して計算します。

from decimal import Decimal, ROUND_HALF_UP
 
print(Decimal(str(0.5)).quantize(Decimal('0'), rounding = ROUND_HALF_UP))
# ⇒ 1

1つ目の「Decimal」は、四捨五入したい数値を文字列で指定します。'文字列で'というのがミソで、数字で指定すると思いがけないズレが生じます。

from decimal import Decimal
 
print(Decimal('123.456'))
# ⇒ 123.456
print(Decimal(123.456))
# ⇒ 123.4560000000000030695446184836328029632568359375

「quantize()」の引数1つ目は、四捨五入したい桁数です。「'0'」は整数に、小数点以下は「'0.1'」「'0.01'」と桁数を増やし、整数部は「'1E1'」と、「E」を使う記述方法で指定します。

from decimal import Decimal, ROUND_HALF_UP
 
a = 123.456
 
print(Decimal(str(a)).quantize(Decimal('0'),rounding = ROUND_HALF_UP))
# ⇒ 123
print(Decimal(str(a)).quantize(Decimal('0.1'),rounding = ROUND_HALF_UP))
# ⇒ 123.5
print(Decimal(str(a)).quantize(Decimal('0.01'),rounding = ROUND_HALF_UP))
# ⇒ 123.46
 
print(int(Decimal(str(a)).quantize(Decimal('1E1'),rounding = ROUND_HALF_UP)))
# ⇒ 120
print(int(Decimal(str(a)).quantize(Decimal('1E2'),rounding = ROUND_HALF_UP)))
# ⇒ 100
print(int(Decimal(str(a)).quantize(Decimal('1E3'),rounding = ROUND_HALF_UP)))
# ⇒ 0

整数部での四捨五入は「1.2E+2」などと「E」がつく表記で返されるので、「int()」で数値に変換することで扱いやすくなります。

「quantize()」の引数2つ目は、丸め方を指定します。
一般的な四捨五入は「ROUND_HALF_UP」、五捨六入は「ROUND_HALF_DOWN」で、いずれもインポートが必要です。
丸め方は執筆時で8つあり、詳しくは公式ドキュメントをご覧ください。

 

round関数ではダメなの?

偶数丸めなので、一般的な四捨五入と異なります。

print(round(0.5))
# ⇒ 0
print(round(1.5))
# ⇒ 2
print(round(2.5))
# ⇒ 2
print(round(3.5))
# ⇒ 4
print(round(4.5))
# ⇒ 4

ご覧の通り、「1.5」は「2」に四捨五入されていますが、「0.5」や「2.5」は切り捨てされています。
一般的な四捨五入をしたいなら、「Decimal.quantize()」を使うほうが良いでしょう。

 

切り上げするには?

整数部だけで良ければ、標準ライブラリ「math」の「ceil()」を使うのが簡単です。

import math
 
print(math.ceil(123.456))
# ⇒ 124

桁数を指定したい場合は、「Decimal.quantize()」の丸め方を「ROUND_CEILING」にします。

from decimal import Decimal, ROUND_CEILING
 
print(Decimal('123.456').quantize(Decimal('0.1'),rounding = ROUND_CEILING))
# ⇒ 123.5

 

切り捨てするには?

整数部だけなら、標準ライブラリ「math」の「floor()」を使います。

import math
 
print(math.floor(123.456))
# ⇒ 123

桁数を指定したい場合は、「Decimal.quantize()」の丸め方を「ROUND_FLOOR」にします。

from decimal import Decimal, ROUND_FLOOR
 
print(Decimal('123.456').quantize(Decimal('0.1'),rounding = ROUND_FLOOR))
# ⇒ 123.4

 

まとめ

Pythonで四捨五入をするなら、「round()」ではなく、「Decimal.quantize()」を使います。
簡単な切り上げと切り捨ては、「math.ceil()」と「math.floor()」を使うとできますし、細かい指定をしたいなら「Decimal.quantize()」を使います。
状況によって使い分けられるよう、知識を整理しておくのが大切ですね。

-Python
-, , , , , , , , , , , , , , , ,