3.

Python round 関数 完全ガイド(銀行家の丸め / 桁数指定 / Decimal / int との違い)

編集
この記事の要点
  • round(x, ndigits) は Python の組み込み関数。数値を指定桁数で丸める
  • 四捨五入ではなく「銀行家の丸め」(偶数丸め)round(0.5) == 0 / round(1.5) == 2
  • ndigits 省略時は整数 (int) を返す。指定時は元の型 (float/Decimal) を保持
  • 浮動小数点誤差で round(2.675, 2) == 2.67 など意外な結果になる — 厳密な金額計算は Decimal を使う
  • 日本式四捨五入が必要なら Decimal + ROUND_HALF_UP や独自関数で対応

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))         # <class 'int'>
type(round(3.5, 0))      # <class 'float'>  ← 注意
type(round(3.5, 2))      # <class 'float'>

「銀行家の丸め」の罠

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.iscloseDecimal を使う。

Q: NumPy の np.round と違う?
A: NumPy も同じく銀行家の丸め。配列に対しては要素ごとに適用される。

Q: 切り上げ / 切り捨てだけしたい
A: math.ceil (切り上げ) / math.floor (切り捨て)。小数桁を指定したい場合は math.ceil(x * 100) / 100 のように工夫。

Q: 表示するだけなら round 不要?
A: 表示用ならf-string や format で十分。round は計算結果として丸めた値そのものが必要な場合に使う。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. max
  2. min
  3. round
  4. range(連続した整数を生成する)

最近更新/作成されたページ