Python
で数値を四捨五入する方法を説明したいと思います。 Python 2
系と Python 3
系では実装方法が異なるので注意が必要です。
前提条件
- Python : 2.7.16
- Python : 3.8.2
Python 2系での四捨五入
組み込み関数である 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
Python 3系での四捨五入
Python 3
系では Python 2
系と同じように組み込み関数の round
関数を使用しても四捨五入が上手くいきません。
>>> print(round(0.4))
0
>>> print(round(0.5))
0
>>> print(round(0.6))
1
このように「 0.5
」の四捨五入を行っても「 0
」となります。これは Python 3
系では 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
また、こちらのサイトにもあるように round
関数では浮動小数点を正確に表すことができないため、計算結果が偶数への丸めになっていないように見える場合もあるようです。
このように Python 3
系の組み込み関数である round
関数では一般的に使用されている四捨五入ではない値が返ってくるため、他の方法で四捨五入を行う必要があります。
標準ライブラリの decimal モジュールの quantize 関数を使用する
Python 3
系で四捨五入するためには標準ライブラリの 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
rounding
に ROUND_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系それぞれの実装方法をきちんと覚えておきたいですね。今回のように四捨五入のやり方ひとつとっても実装方法が全然異なるので・・・。バージョンが上がって実装方法が複雑になるのはいかがなものかとも思いますが、こればっかりはしょうがないので四捨五入のやり方しっかりマスターしたいですね。
コメント