Python で四捨五入したい

まず先に結論を書いてしまうと、Python で四捨五入する場合には、以下の様なコードで実現できます。

# 必要なモジュールとメソッドをインポート

from decimal import Decimal, ROUND_HALF_UP

 

# この数を四捨五入
f = 123.456

 

# 小数第一位で四捨五入し、整数とする
print(Decimal(str(f)).quantize(Decimal('0'), rounding=ROUND_HALF_UP))

# 小数第二位で四捨五入し、小数第一位までとする 
print(Decimal(str(f)).quantize(Decimal('0.1'), rounding=ROUND_HALF_UP))

# 小数第三位で四捨五入し、小数第二位までとする 
print(Decimal(str(f)).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP))

実行すると、以下の様になります。

123
123.5
123.46

 

コード内にコメントを入れているので、大まかな部分は問題ないと思いますが、実際に四捨五入している部分について補足説明します。

まずは、「Decimal(str(f))」の部分について。
ここでは「Decimal」型を使って正確な値を取得しています。浮動小数点型として使われている「float」型は一見正確な値を扱っているように見えますが、厳密には違っています。以下の様なコードを書くと理解しやすいです。

# 必要モジュール、メソッドをインポート
from decimal import Decimal

# float型変数を定義
f = 0.05


# float型変数をそのまま表示
print(f)

# Decimal型変数に変換して表示
print(Decimal(f))

実行すると、以下の様になります。

0.05
0.05000000000000000277555756156289135105907917022705078125

1行目は確かに元のfloat型変数の値がそのまま表示されましたが、2行目のDecimal型変数を表示している行は微妙な差が発生しています。
コンピュータ内では数値を「2のn乗」の形で表示しているため、値を正確に表示するDecimal型変数で表示すると見えた差分です。

 

ここまで理解した上で、改めて元コードの「Decimal(str(f))」を見てみると、float型変数の「123.456」をDecimal型変数に置き換える前に、str型に置き換えています(「str(f)」部分)。
これは、先ほど説明したようにfloat型変数をそのまま渡すと微妙な誤差が発生してしまうために、一旦文字列として誤差が無い状態にしています。その誤差が無い状態にしてから、Decimal型変数ににすることで、正確な値をDecimal型変数として扱っています。

 

続いて「quantize(Decimal('0'), rounding=ROUND_HALF_UP)」の部分についてです。
まず、「quantize」メソッドで丸め方を指定することが出来ます。
第一引数の「Decimal('0')」や「(Decimal('0.1')」は、丸めた後の桁数を指定することが出来ます。例えば「(Decimal('0.1')」と指定された場合は、丸めた後の桁数を小数第一位までの値とすることが出来ます。

続いて第二引数の「rounding=ROUND_HALF_UP)」で四捨五入を指定しています。他にも「ROUND_HALF_EVEN」を指定すると偶数への丸めとなるらしいので、詳しく知りたい方は下部の参考サイトをご覧ください。

 

参考:

note.nkmk.me

 

 

 

 

Python で外部モジュールを利用したい

Python では、外部モジュールを使うと簡単にコードを書くことが出来ます。

 

例えば、最近書いた以下の記事を例にあげると、

こんなコードを書いていました。

import itertools

test_list = [1,2,3,4]
for pairs in itertools.combinations(test_list, 2):
    print(pairs)

このコードでは、全パターン網羅をするために、
1行目で「itertools」モジュールをインポートし、
3行目で該当モジュール内の「combinations」メソッドを使っています。

 

この様に書くと、外部モジュールを使えて簡単にコードを書くことが出来ますが、
「itertools.combinations」って書くのは面倒くさいし、入力ミスしそうです。
そこで使うのが「from」と「import」の組み合わせ。

「from」と「import」を使って上記のコードを書き換えると、以下の様になります。

from itertools import combinations

test_list = [1,2,3,4]
for pairs in combinations(test_list, 2):
    print(pairs)

このコードでは、
1行目で「itertools」モジュールの「combinations」メソッドをインポートし、
3行目で「combinations」メソッド名のみで使っています。

 

参考サイト:

note.nkmk.me