Python PR

【Python】小数の切り上げ・切り捨て・四捨五入

記事内に商品プロモーションを含む場合があります

この記事では、Pythonで小数を切り上げ、切り捨て、四捨五入する方法を解説します。

切り上げ math.ceil()
切り捨て math.floor()
四捨五入 round() または Decimal.quantize()

四捨五入は、値が正確じゃなくていいならround()関数を使い、正確に取得したい場合はDecimal.quantize()を使うという感じでいいと思います。

それでは、もう少し詳しく見ていきましょう!

切り上げ

小数点を切り上げるには、mathモジュールのceil()関数を使います。mathモジュールは、標準ライブラリなのでインポートするだけで使えます。

import math

math.ceil(x)

ceil()関数は、x引数以上の最小の整数を返します。

import math

print(f'1.1 = {math.ceil(1.1)}')
print(f'1.9 = {math.ceil(1.9)}')
print(f'0.5 = {math.ceil(0.5)}')

# 型を調べてみる
print(type(math.ceil(1.1)))

実行結果

1.1 = 2
1.9 = 2
0.5 = 1
<class 'int'>

四捨五入ではなく切り上げな点に注意してください。

切り捨て

小数点を切り捨てるには、mathモジュールのfloor()関数を使います。

import math

math.floor(x)

floor()関数は、x引数以下の最大の整数を返します。

import math

print(f'{1.1} = {math.floor(1.1)}')
print(f'{1.9} = {math.floor(1.9)}')
print(f'{0.5} = {math.floor(0.5)}')

実行結果

1.1 = 1
1.9 = 1
0.5 = 0

必ず切り捨てられる点に注意してください。

四捨五入

四捨五入をするには、複数の選択肢があるのでそれぞれ見ていきましょう!

round()関数を使った四捨五入

簡単に四捨五入するには、組み込み関数であるround()関数を使います。

round(number[, ndigits])

round()関数は、number引数の小数をndigits引数の桁に丸めた値を返します。ndigits引数を省略するかNoneだった場合、整数で返されます。

print(f'{1.1} = {round(1.1)}')
print(f'{1.9} = {round(1.9)}')
print(f'{0.5} = {round(0.5)}')

実行結果

1.1 = 1
1.9 = 2
0.5 = 0

先ほどのサンプルコードで「0.5」をround()関数で処理したら「0」になっていました。実はround()関数は、端数が「0.5」より小さいなら切り捨て、端数が「0.5」より大きいならは切り上げ、端数が「0.5」なら結果が偶数となる方へ丸められます。

print(f'{0.5} = {round(0.5)}')
print(f'{1.5} = {round(1.5)}')
print(f'{2.5} = {round(2.5)}')
print(f'{3.5} = {round(3.5)}')

実行結果

0.5 = 0
1.5 = 2
2.5 = 2
3.5 = 4

また、小数第二位以下では偶数に丸められないこともある。

print(f'{0.05} = {round(0.05, 1)}')
print(f'{0.15} = {round(0.15, 1)}')
print(f'{0.25} = {round(0.25, 1)}')
print(f'{0.35} = {round(0.35, 1)}')

実行結果

0.05 = 0.1
0.15 = 0.1
0.25 = 0.2
0.35 = 0.3

浮動小数点数は、計算機内部で2進数の分数で表現されています。なのでどうしてもズレが生じ、このような問題が起こってしまう。

正確に四捨五入したい場合はround()関数は向いていない。値の正確さが重要な場合は、Decimalクラスを使うか自作関数を定義した方が安全です!

Decimal.quantize()を使った四捨五入

Decimalクラスは、正確に10進数を扱えるクラスで四捨五入もできます。decimalモジュールは標準ライブラリなのでインポートするだけで使えます。

正確な10進数でオブジェクトを生成するには、str型で値を指定します。

import decimal

# 正確な10進数の0.5でインスタンス化
d = decimal.Decimal('0.5')

print(d)

実行結果

0.5

Decimalクラスで四捨五入するにはquantize()メソッドを使います。

Decimal.quantize(exp, rounding=None, context=None)

exp引数に、Decimalクラスを使って求めたい桁数と同じ桁の値を指定します。

rounding引数には、丸めモードをdecimalモジュールの定数を使って指定します。丸めモードについては以下のリンクを参考にしてください。

Link丸めモード - decimal --- 十進固定及び浮動小数点数の算術演算 — Python ドキュメント

四捨五入したい場合は、ROUND_HALF_UPを指定しましょう!

from decimal import Decimal, ROUND_HALF_UP

e = 2.71828182846

print(Decimal(str(e)).quantize(Decimal('1.0'), ROUND_HALF_UP))
print(Decimal(str(e)).quantize(Decimal('1.00'), ROUND_HALF_UP))
print(Decimal(str(e)).quantize(Decimal('1.000'), ROUND_HALF_UP))

実行結果

2.7
2.72
2.718

自作関数で四捨五入

四捨五入は以下のような感じで定義できる。

def my_round(num, digit=0):
    p = 10 ** digit
    r = (num * p * 2 + 1) // 2 / p
    if digit == 0:
        r = int(r)
    return r

試しに先ほどの関数を使ってみます。

def my_round(num, digit=0):
    p = 10 ** digit
    r = (num * p * 2 + 1) // 2 / p
    if digit == 0:
        r = int(r)
    return r


print(f'1.1 = {my_round(1.1)}')
print(f'1.9 = {my_round(1.9)}')
print(f'0.5 = {my_round(0.5)}')

print(f'0.01 = {my_round(0.01, 1)}')
print(f'0.19 = {my_round(0.19, 1)}')
print(f'0.05 = {my_round(0.05, 1)}')

実行結果

1.1 = 1
1.9 = 2
0.5 = 1
0.01 = 0.0
0.19 = 0.2
0.05 = 0.1

まとめ

この記事では、小数点を切り上げ、切り捨て、四捨五入する方法を解説しました。

切り上げと切り捨ては単純でしたが四捨五入は意外とゴチャゴチャしていました。値が大体でいいならround()関数を使い、正確に欲しい場合はDecimal.quantize()を使いましょう!

それでは今回の内容はここまでです。ではまたどこかで〜( ・∀・)ノ