タイトル: round
SEOタイトル: Python round 関数 完全ガイド(銀行家の丸め / 桁数指定 / Decimal / int との違い)
| この記事の要点 |
|
round 関数とは
round は Python の組み込み関数で、数値を指定した桁数で丸める機能を持ちます。「四捨五入」と認識されがちですが、実際は銀行家の丸め (Banker's Rounding) という別ルールで動作する点に注意が必要です。
構文
round(number, ndigits=None)
| 引数 | 説明 |
|---|---|
number | 丸める数値 (int / float / Decimal) |
ndigits | 残す小数点以下の桁数。負の整数で整数部分を丸めも可能。省略時は整数化 |
基本例
# 小数第 2 位で丸め
print(round(10.456, 2)) # 10.46
# 小数点以下を切り捨てて整数化 (ndigits 省略)
print(round(3.7)) # 4
print(round(3.4)) # 3
# 負の桁: 整数部分の丸め
print(round(1234.5, -1)) # 1230
print(round(1234.5, -2)) # 1200
戻り値の型
- ndigits 省略時: int を返す
- ndigits 指定時: 元の型を保持 (float なら float、Decimal なら Decimal)
type(round(3.5)) #
type(round(3.5, 0)) # ← 注意
type(round(3.5, 2)) #
「銀行家の丸め」の罠
Python 3 の round は偶数丸め (Banker's Rounding) を採用しています。.5 のとき、結果が偶数になる方に丸めます。
# 偶数丸め: 学校で習った四捨五入と違う!
print(round(0.5)) # 0 (1 ではなく)
print(round(1.5)) # 2
print(round(2.5)) # 2 (3 ではなく)
print(round(3.5)) # 4
print(round(4.5)) # 4 (5 ではなく)
これは大量データの平均で誤差を相殺するためのルールで、統計・金融業界の標準。IEEE 754 規格にも準拠しています。
浮動小数点誤差の罠
float の内部表現が 2 進数のため、見た目と異なる値で丸めが行われる場合があります。
print(round(2.675, 2)) # 2.67 ← 直感では 2.68 のはず
# 内部では 2.6749999999999998... なので 2.67 に丸まる
print(f"{2.675:.20f}") # 2.67499999999999982236
厳密な小数計算が必要な場面 (金額計算など) では絶対に float を使わないのが鉄則。
厳密な計算には Decimal を使う
標準ライブラリの decimal モジュールを使えば、任意精度で正確な丸めが可能。日本式の四捨五入 (ROUND_HALF_UP) も指定できます。
from decimal import Decimal, ROUND_HALF_UP
# 通常の round と挙動が違う
x = Decimal("2.675")
y = x.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
print(y) # 2.68 ← 日本式四捨五入
# 銀行家の丸めを Decimal で
from decimal import ROUND_HALF_EVEN
y2 = x.quantize(Decimal("0.01"), rounding=ROUND_HALF_EVEN)
print(y2) # 2.68
# 文字列で渡すのが重要 (float 経由だと誤差が乗る)
z = Decimal(2.675).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
print(z) # 2.67 ← float 経由で誤差混入
日本式四捨五入の実装パターン
どうしても float のまま四捨五入したい場合の独自関数。
def round_half_up(x, ndigits=0):
"""日本式四捨五入"""
p = 10 ** ndigits
if x >= 0:
return int(x * p + 0.5) / p
else:
return -int(-x * p + 0.5) / p
print(round_half_up(0.5)) # 1
print(round_half_up(2.5)) # 3
print(round_half_up(2.675, 2)) # 2.68 (誤差を吸収できる範囲なら)
ただし上記もすべての浮動小数点誤差を吸収できるわけではありません。精度が必要なら必ず Decimal。
負の桁数で整数部を丸める
print(round(15499, -2)) # 15500
print(round(15499, -3)) # 15000
print(round(15500, -3)) # 16000 ← 銀行家の丸め (15 が奇数なので 16 へ)
print(round(15500, -2)) # 15500
請求金額の1000 円単位丸めや有効数字の制限に便利です。
類似の方法との比較
| 方法 | 挙動 | 用途 |
|---|---|---|
round(x, n) | 銀行家の丸め | 統計 / 一般的な丸め |
int(x) | 0 方向に切り捨て | 整数化 |
math.floor(x) | 負の無限方向へ切り捨て | 常に小さい方へ |
math.ceil(x) | 正の無限方向へ切り上げ | 常に大きい方へ |
math.trunc(x) | 0 方向に切り捨て (int 相当) | 負数を含む整数化 |
Decimal.quantize(...) | 丸めモード指定可能 | 金額 / 精密計算 |
f"{x:.2f}" | 文字列フォーマット (四捨五入) | 表示用 |
表示専用なら f-string が便利
x = 10.456
print(f"{x:.2f}") # 10.46
print(f"{0.5:.0f}") # 0 ← これも銀行家の丸め
print(f"{1234.567:,.2f}") # 1,234.57 ← カンマ区切り
FAQ
Q: 0.1 + 0.2 == 0.3 が False になる
A: 浮動小数点表現の宿命。round(0.1 + 0.2, 10) で比較するか、math.isclose や Decimal を使う。
Q: NumPy の np.round と違う?
A: NumPy も同じく銀行家の丸め。配列に対しては要素ごとに適用される。
Q: 切り上げ / 切り捨てだけしたい
A: math.ceil (切り上げ) / math.floor (切り捨て)。小数桁を指定したい場合は math.ceil(x * 100) / 100 のように工夫。
Q: 表示するだけなら round 不要?
A: 表示用ならf-string や format で十分。round は計算結果として丸めた値そのものが必要な場合に使う。