本記事では、Pythonで四捨五入・切り上げ・切り捨てを行う方法を、
「変数」・「list(配列)」・「NumPy配列」・「pandas DataFrame」
の4パターンに分けて解説します。
特に、round 関数が「4.5 を 5 ではなく 4 に丸める」理由や、decimal モジュールを用いた
一般的な四捨五入(5 を常に切り上げる方式)の実装方法など、実務でもつまずきやすいポイントを丁寧に扱います。
こんな人におすすめ
- Pythonの変数を四捨五入・切り上げ・切り捨てしたい
- Pythonの配列(list)を一気に四捨五入・切り上げ・切り捨てしたい
- NumPy配列を一気に四捨五入・切り上げ・切り捨てしたい
- pandasのDataFrameを一気に四捨五入・切り上げ・切り捨てしたい
主なライブラリ
本ページでは、以下のモジュール・ライブラリを利用します。
decimalモジュール(Decimalクラスによる厳密な四捨五入)mathモジュール(ceil,floor)pandasnumpy
事前に以下のようにインポートしておきます。
import math import pandas as pd import numpy as np from decimal import Decimal, ROUND_HALF_UP, ROUND_DOWN, ROUND_UP
Python変数の丸め処理(四捨五入・切り上げ・切り捨て)
まずは、単一の変数(スカラー値)に対して丸め処理を行う方法を紹介します。
Python標準の round 関数と、decimal モジュールの Decimal クラスを使った方法を比較しながら見ていきます。
Python変数(四捨五入)
decimal モジュールの Decimal クラスと、そのメソッド quantize を使用すると、
「一般的な四捨五入(5 を常に切り上げ)」を実装できます。
- Decimal の引数:四捨五入したい変数を文字列型で渡す(浮動小数点誤差を避けるため)。
- quantize の第1引数:四捨五入後の小数点以下の桁数を
Decimal('0.1')のように指定。 - quantize の第2引数:
rounding=ROUND_HALF_UPを指定すると、5 を常に切り上げる一般的な四捨五入になります。
i = 1.234
print(Decimal(str(i)).quantize(Decimal('1'), rounding=ROUND_HALF_UP))
# ⇒ 1
print(Decimal(str(i)).quantize(Decimal('0.1'), rounding=ROUND_HALF_UP))
# ⇒ 1.2
print(Decimal(str(i)).quantize(Decimal('0.01'), rounding=ROUND_HALF_UP))
# ⇒ 1.23
Python変数の四捨五入では round 関数がよく使われますが、
「銀行丸め(偶数丸め)」 という方式で動作するため、
学校で習う一般的な四捨五入(5 以上は一律で切り上げ)とは結果が異なることがあります。
下記は、round 関数が偶数丸めで動作している例です。
一般的な四捨五入では 4.5 → 5 になりますが、Python の round では 4.5 → 4 になります。
# 学校で習う一般的な四捨五入では 4.5 → 5 になるが、 # round 関数は「偶数丸め」をしているため、4 が返ってくる。 i = 4.5 print(round(i)) # ⇒ 4 # この場合は、一般的な四捨五入と同じ結果が返ってくる j = 5.5 print(round(j)) # ⇒ 6
正確な四捨五入(5 を常に切り上げる方式)が必要な場合は、
round ではなく decimal モジュール(Decimal + ROUND_HALF_UP)
を使用することをおすすめします。
Python変数(切り上げ)
変数の切り上げには math.ceil を使用します。
小数第1位だけでなく、第2位・第3位など任意の桁で切り上げたい場合は、
いったん数値を 10 倍・100 倍したうえで ceil を適用し、最後に元のスケールに戻します。
i = 1.2345 # 小数点第1位を切り上げる print(math.ceil(i)) # ⇒ 2 # 小数点第2位を切り上げる print(math.ceil(i * 10) / 10) # ⇒ 1.3
decimal モジュールを使って、より厳密に切り上げることも可能です。
i = 1.2345
# 小数点第1位を切り上げる
print(Decimal(str(i)).quantize(Decimal('1'), rounding=ROUND_UP))
# ⇒ 2
# 小数点第2位を切り上げる
print(Decimal(str(i)).quantize(Decimal('0.1'), rounding=ROUND_UP))
# ⇒ 1.3
Python変数(切り捨て)
変数の切り捨てには math.floor を使用します。考え方は ceil と同様です。
i = 1.2345 # 小数点第1位を切り捨てる print(math.floor(i)) # ⇒ 1 # 小数点第2位を切り捨てる print(math.floor(i * 10) / 10) # ⇒ 1.2
decimal モジュールを使って切り捨てることも可能です。
i = 1.2345
# 小数点第1位を切り捨てる
print(Decimal(str(i)).quantize(Decimal('1'), rounding=ROUND_DOWN))
# ⇒ 1
# 小数点第2位を切り捨てる
print(Decimal(str(i)).quantize(Decimal('0.1'), rounding=ROUND_DOWN))
# ⇒ 1.2
Python配列(list)の丸め処理
Python の list(配列)そのものに対して、一括で四捨五入する専用関数は用意されていません。
しかし、list はイテラブルなので、内包表記や for 文 を使って要素ごとに丸め処理を行うことができます。
Python配列(四捨五入)
例として、次のような list を四捨五入してみます。
list1 = [1.234, 3.456, 5.678]
Decimal を使った場合と、round を使った場合の両方を示します。
# Decimal を使った一般的な四捨五入(5 を常に切り上げ)
print([Decimal(str(i)).quantize(Decimal('0.1'), rounding=ROUND_HALF_UP) for i in list1])
# ⇒ [Decimal('1.2'), Decimal('3.5'), Decimal('5.7')]
# round を使った場合(偶数丸め)
print([round(i, 1) for i in list1])
# ⇒ [1.2, 3.5, 5.7]
Decimal を利用した四捨五入処理は、実行結果が
[Decimal('1.2'), Decimal('3.5'), Decimal('5.7')] のように表示されます。
これは通常の小数とほぼ同様に数値計算に利用できますが、
型としては float ではなく Decimal 型である点に注意してください。
Python配列(切り上げ)
切り上げ・切り捨ても同様に、list の各要素に対して math.ceil や math.floor を適用します。
list1 = [1.234, 3.456, 5.678] print([math.ceil(i) for i in list1]) # ⇒ [2, 4, 6]
Python配列(切り捨て)
list1 = [1.234, 3.456, 5.678] print([math.floor(i) for i in list1]) # ⇒ [1, 3, 5]
NumPy配列の丸め処理
NumPy には np.round, np.ceil, np.floor といった丸め系の関数が用意されています。
ただし np.round も Python の round と同様に
偶数丸め(銀行丸め) で動作します。
「5 を常に切り上げる一般的な四捨五入」が必要な場合は、
Decimal を使った自作関数を np.vectorize などで適用する方法があります。
なお、np.vectorize は見た目はベクトル化されていますが、内部的には Python ループに近いため、
性能がシビアな場合は np.floor などを組み合わせた数式ベースの実装も検討してください。
NumPy配列(四捨五入)
list2 = np.array([
[1.234, 3.456, 5.678],
[5.432, 6.543, 8.765]
])
# Decimal を利用する場合(一般的な四捨五入)
def func_ROUND_HALF_UP(x):
return Decimal(str(x)).quantize(Decimal('0.1'), rounding=ROUND_HALF_UP)
print(np.vectorize(func_ROUND_HALF_UP)(list2))
# [[Decimal('1.2') Decimal('3.5') Decimal('5.7')]
# [Decimal('5.4') Decimal('6.5') Decimal('8.8')]]
# np.round を利用する場合(偶数丸め)
print(np.round(list2, 1))
# [[1.2 3.5 5.7]
# [5.4 6.5 8.8]]
Decimal を利用した四捨五入処理の結果は
[[Decimal('1.2') ...]] のように Decimal 型で表現されます。
通常の数値とほぼ同様に扱えますが、型が float とは異なるため、
他の NumPy 関数との組み合わせでは注意が必要です。
NumPy配列(切り上げ)
list2 = np.array([
[1.234, 3.456, 5.678],
[5.432, 6.543, 8.765]
])
print(np.ceil(list2))
# [[2. 4. 6.]
# [6. 7. 9.]]
NumPy配列(切り捨て)
list2 = np.array([
[1.234, 3.456, 5.678],
[5.432, 6.543, 8.765]
])
print(np.floor(list2))
# [[1. 3. 5.]
# [5. 6. 8.]]
pandas DataFrame の丸め処理
pandas の DataFrame には round メソッドが用意されています。
こちらも round / np.round と同様に
偶数丸め で動作します。
一般的な四捨五入が必要な場合は、自作関数と agg を組み合わせて使います。
pandasのDataFrame(四捨五入)
df = pd.DataFrame({'a': [1.23, 2.34, 3.45],
'b': [4.4, 4.5, 4.6]})
# a b
# 0 1.23 4.4
# 1 2.34 4.5
# 2 3.45 4.6
# 一般的な四捨五入(5 を常に切り上げ)を行う関数
def func_ROUND_HALF_UP(list1):
return [Decimal(str(i)).quantize(Decimal('1'), rounding=ROUND_HALF_UP) for i in list1]
print(df.agg(func_ROUND_HALF_UP))
# a b
# 0 1 4
# 1 2 5
# 2 3 5
# DataFrame.round() を使った場合(偶数丸め)
print(df.round())
# a b
# 0 1.0 4.0
# 1 2.0 4.0 # ⇒ 偶数丸め
# 2 3.0 5.0
上記では agg を用いて列ごとに自作関数を適用しています。
行方向・列方向にどのように適用されるかは、DataFrame の構造と関数の戻り値に依存しますので、
実際の業務データに合わせて挙動を確認しながら利用してください。
pandasのDataFrame(切り上げ)
DataFrame 全体を切り上げる場合は、agg を用いて np.ceil を適用します。
print(df.agg(np.ceil)) # a b # 0 2.0 5.0 # 1 3.0 5.0 # 2 4.0 5.0
pandasのDataFrame(切り捨て)
print(df.agg(np.floor)) # a b # 0 1.0 4.0 # 1 2.0 4.0 # 2 3.0 4.0
用途別のおすすめ丸め方法まとめ
最後に、用途ごとにどの方法を選べばよいか、ざっくりとまとめます。
| シチュエーション | おすすめ手法 |
|---|---|
| 学習用・簡単なスクリプト | round(偶数丸めであることを理解した上で使用) |
| 金額計算など、厳密な四捨五入が必要 | Decimal + ROUND_HALF_UP(一般的な四捨五入) |
| 大規模な配列計算(NumPy) | np.round(偶数丸め)や、np.floor 等を組み合わせた独自実装 |
| 分析用の表形式データ(pandas DataFrame) | DataFrame.round や、自作関数 + agg |
よくある質問(FAQ)
Q. なぜ round(4.5) は 5 ではなく 4 になるのですか?
Python の round 関数は、「5 を常に切り上げる一般的な四捨五入」ではなく、
偶数丸め(銀行丸め) を採用しているためです。
小数部分がちょうど 0.5 の場合、近い偶数に丸められる仕様になっています。
Q. 一般的な四捨五入をしたいときはどうすればよいですか?
一般的な四捨五入(5 を常に切り上げ)を行いたい場合は、
decimal モジュールの Decimal クラスと
ROUND_HALF_UP を利用してください。
本記事のサンプルコードのように quantize メソッドを使うと簡単に実現できます。
Q. NumPy配列やpandas DataFrame でも Decimal を使うべきですか?
金額計算など厳密な結果が求められる場合は Decimal を検討すべきですが、
Decimal は float とは型が異なるため、
NumPy や pandas の一部機能と組み合わせる際に制約が出ることがあります。
性能・保守性・必要な精度のバランスを考慮して選択してください。


![[python]CSVをPandasに出力(1列目、列指定、桁数)](https://machine-learning-skill-up.com/knowledge/wp-content/uploads/2023/11/1-288.jpg)


