プログラミング

[Python]数値を四捨五入する

プログラミング
この記事は約7分で読めます。
スポンサーリンク

Pythonで数値を四捨五入する方法を説明したいと思います。Python2Python3では実装方法が異なるので注意が必要です。

スポンサーリンク

前提条件

  • Python:2.7.16
  • Python:3.8.2

Python2系での四捨五入

組み込み関数であるround関数を使用して四捨五入することができます。

小数の四捨五入

>>> print(round(0.4))
0.0
>>> print(round(0.5))
1.0
>>> print(round(0.6))
1.0

第2引数に何も指定しない場合、round関数は小数点第一位で四捨五入を行います。小数点第二位で四捨五入を行いたい場合、round関数の第2引数に「1」を指定します。

>>> print(round(0.45, 1))
0.5

整数の四捨五入

>>> print(round(4, -1))
0.0
>>> print(round(5, -1))
10.0
>>> print(round(6, -1))
10.0

round関数の第2引数に「-1」を指定すると一の位での四捨五入を行います。十の位で四捨五入したい場合は、第2引数に「-2」を指定します。

>>> print(round(50, -2))
100.0

Python3系での四捨五入

Python3系ではPython2系と同じように組み込み関数のround関数を使用しても四捨五入が上手くいきません。

>>> print(round(0.4))
0
>>> print(round(0.5))
0
>>> print(round(0.6))
1

このように「0.5」の四捨五入を行っても「0」となります。これはPython3系ではround関数は「偶数への丸め」を行う関数へ変更されているのが原因です。

偶数への丸め(round to even)とは

端数が0.5より小さいなら切り捨てを行い、端数が0.5より大きいならは切り上げを行います。ここまでは四捨五入と同じなのですが、端数がちょうど0.5なら切り捨てと切り上げのうち結果が偶数となる方へ丸められます。これにより、「0.5」をround関数で四捨五入しようとすると、切り上げると「1」となり奇数となるので、切り捨てとなり「0」が返ってきます。

ちなみに「1.5」をround関数で四捨五入しようとすると切り上げると偶数になるので「2」が返ってきます。

>>> print(round(0.5))
0
>>> print(round(1.5))
2
端数処理 - Wikipedia

また、こちらのサイトにもあるようにround関数では浮動小数点を正確に表すことができないため、計算結果が偶数への丸めになっていないように見える場合もあるようです。

組み込み関数 — Python 3.9.4 ドキュメント

このようにPython3系の組み込み関数であるround関数では一般的に使用されている四捨五入ではない値が返ってくるため、他の方法で四捨五入を行う必要があります。

標準ライブラリのdecimalモジュールのquantize関数を使用する

Python3系で四捨五入するためには標準ライブラリのdecimalモジュールを使用する必要があります。

基本的な手順は下記の通り。

  • decimalモジュールをインポートする
  • 四捨五入を行う値をDecimal型へ変換する
  • quantize関数を利用して四捨五入を行う
>>> from decimal import Decimal, ROUND_HALF_UP
>>> print(Decimal(str(0.4)).quantize(Decimal('0'), rounding=ROUND_HALF_UP))
0
>>> print(Decimal(str(0.5)).quantize(Decimal('0'), rounding=ROUND_HALF_UP))
1
>>> print(Decimal(str(0.6)).quantize(Decimal('0'), rounding=ROUND_HALF_UP))
1

roundingROUND_HALF_UPを指定すると一般的な四捨五入となります。

quantize関数の第一引数を「0.1」や「0.01」に変更することで四捨五入を行う位を変更できます。

>>> n = 123.456
>>>
>>> print(Decimal(str(n)).quantize(Decimal('0'), rounding=ROUND_HALF_UP))
123
>>> print(Decimal(str(n)).quantize(Decimal('0.1'), rounding=ROUND_HALF_UP))
123.5
>>> print(Decimal(str(n)).quantize(Decimal('0.2'), rounding=ROUND_HALF_UP))
123.5

これで小数の四捨五入はできるようになりましたが、整数は同じ方法では四捨五入できません。

整数の四捨五入

整数の四捨五入の場合は、quantize関数の第一引数の部分を指数表記で桁数を指定する必要があります。

>>> print('4 =>', int(Decimal(4).quantize(Decimal('1E1'), rounding=ROUND_HALF_UP)))
4 => 0
>>> print('5 =>', int(Decimal(5).quantize(Decimal('1E1'), rounding=ROUND_HALF_UP)))
5 => 10
>>> print('6 =>', int(Decimal(6).quantize(Decimal('1E1'), rounding=ROUND_HALF_UP)))
6 => 10

こんな感じで四捨五入する位を変更することができます。

# 一の位を四捨五入
>>> print('55555 =>', int(Decimal(55555).quantize(Decimal('1E1'), rounding=ROUND_HALF_UP)))
55555 => 55560

# 十の位を四捨五入
>>> print('55555 =>', int(Decimal(55555).quantize(Decimal('1E2'), rounding=ROUND_HALF_UP)))
55555 => 55600

# 百の位を四捨五入
>>> print('55555 =>', int(Decimal(55555).quantize(Decimal('1E3'), rounding=ROUND_HALF_UP)))
55555 => 56000

# 千の位を四捨五入
>>> print('55555 =>', int(Decimal(55555).quantize(Decimal('1E4'), rounding=ROUND_HALF_UP)))
55555 => 60000

最後に

Pythonは2系と3系で使い勝手がかなり変わっているので、2系から3系の変更点や2系、3系それぞれの実装方法をきちんと覚えておきたいですね。今回のように四捨五入のやり方ひとつとっても実装方法が全然異なるので・・・。バージョンが上がって実装方法が複雑になるのはいかがなものかとも思いますが、こればっかりはしょうがないので四捨五入のやり方しっかりマスターしたいですね。

スポンサーリンク
スポンサーリンク
KoEをフォローする
CodeLab

コメント

タイトルとURLをコピーしました