Python標準の round() 関数は「偶数丸め(銀行丸め)」を採用しているため、一般的な「四捨五入」とは異なる結果になることがあります。
金融計算など、厳密なルールに基づいた端数処理が必要な場合は、標準ライブラリの decimal モジュールを使用します。このモジュールの quantize() メソッドを使うことで、四捨五入だけでなく、切り上げ、切り捨てなど、多様な丸め処理を正確に制御できます。
この記事では、decimal モジュールで使用できる丸めモードの一覧と、小数点以下および整数部分での丸め計算の実装方法について解説します。
目次
Decimalの丸めモード一覧
decimal モジュールには、以下の定数が定義されており、quantize() メソッドの引数として渡すことで丸め方を指定できます。
| 定数名 | 意味 | 動作の例 (正の数) |
ROUND_HALF_UP | 四捨五入 | 最も近い数字に丸める。中間値(0.5)は0から遠い方へ(切り上げ)。 |
ROUND_HALF_DOWN | 五捨六入 | 最も近い数字に丸める。中間値(0.5)は0に近い方へ(切り捨て)。 |
ROUND_HALF_EVEN | 偶数丸め | 最も近い数字に丸める。中間値(0.5)は偶数側へ。Python標準の round() と同じ。 |
ROUND_UP | 切り上げ | 0から遠い方向へ丸める(絶対値の切り上げ)。 |
ROUND_DOWN | 切り捨て | 0に近い方向へ丸める(絶対値の切り捨て)。 |
ROUND_CEILING | 正の無限大方向 | 数直線上で右側(大きい方)へ丸める。 |
ROUND_FLOOR | 負の無限大方向 | 数直線上で左側(小さい方)へ丸める。 |
ROUND_05UP | 特殊 | 最後の桁が0か5になるように丸める。 |
日本では一般的に ROUND_HALF_UP(四捨五入) が最もよく使われます。
1. 小数点以下の四捨五入
quantize() メソッドの第1引数に、丸めたい桁数(精度)を表す Decimal オブジェクトを渡します。
- 整数に丸める:
Decimal("0") - 小数第1位まで:
Decimal("0.1") - 小数第2位まで:
Decimal("0.01")
from decimal import Decimal, ROUND_HALF_UP
# 元の数値 (文字列で指定して誤差を防ぐ)
target_value = Decimal("123.4567")
print(f"元の値: {target_value}")
# 1. 整数に丸める (1の位まで)
# "0" を指定すると整数になる
val_int = target_value.quantize(Decimal("0"), rounding=ROUND_HALF_UP)
print(f"整数: {val_int}")
# 2. 小数第1位まで丸める (第2位を四捨五入)
# "0.1" を指定
val_1 = target_value.quantize(Decimal("0.1"), rounding=ROUND_HALF_UP)
print(f"小数第1位: {val_1}")
# 3. 小数第2位まで丸める (第3位を四捨五入)
# "0.01" を指定
val_2 = target_value.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
print(f"小数第2位: {val_2}")
# 4. 小数第3位まで丸める (第4位を四捨五入)
val_3 = target_value.quantize(Decimal("0.001"), rounding=ROUND_HALF_UP)
print(f"小数第3位: {val_3}")
実行結果:
元の値: 123.4567
整数: 123
小数第1位: 123.5
小数第2位: 123.46
小数第3位: 123.457
2. 整数部分(10の位、100の位)での四捨五入
整数の位(10の位や100の位)で丸めたい場合は、quantize() の引数に 指数表記(E表記) を使用します。
- 10の位まで(1の位を四捨五入):
Decimal("1E1") - 100の位まで(10の位を四捨五入):
Decimal("1E2")
from decimal import Decimal, ROUND_HALF_UP
# 丸める対象の整数
large_value = Decimal("56789")
print(f"元の値: {large_value}")
# 1. 10の位まで丸める (1E1 = 10)
# 56789 -> 56790
round_10 = large_value.quantize(Decimal("1E1"), rounding=ROUND_HALF_UP)
print(f"10の位: {round_10}")
# 2. 100の位まで丸める (1E2 = 100)
# 56789 -> 56800
round_100 = large_value.quantize(Decimal("1E2"), rounding=ROUND_HALF_UP)
print(f"100の位: {round_100}")
# 3. 1000の位まで丸める (1E3 = 1000)
# 56789 -> 57000
round_1000 = large_value.quantize(Decimal("1E3"), rounding=ROUND_HALF_UP)
print(f"1000の位: {round_1000}")
実行結果:
元の値: 56789
10の位: 5.679E+4
100の位: 5.68E+4
1000の位: 5.7E+4
結果を通常の数値表記に戻す
上記のように、大きな桁で丸めると結果が指数表記(5.68E+4など)になってしまうことがあります。これを通常の数値文字列に戻すには、int() で変換するか、フォーマット済み文字列を使用します。
# 通常の表記で表示
print(f"100の位(int変換): {int(round_100)}")
print(f"1000の位(f-string): {round_1000:.0f}")
実行結果:
100の位(int変換): 56800
1000の位(f-string): 57000
まとめ
- 厳密な丸め処理には
decimalモジュールを使用します。 quantize()メソッドに、桁数を表すDecimalオブジェクトと、丸めモード定数(ROUND_HALF_UPなど)を渡します。- 小数点の丸め:
Decimal("0.01")のように記述。 - 整数の丸め:
Decimal("1E2")のように指数表記で記述。
