Pythonで割り算を書くとき、/
と//
はまったく別物です。
前者は実数の割り算、後者は小数点以下を切り捨てる割り算です。
特に負の数では結果が直感と違うことがあるため、丸め方向と結果の型を理解してから使うことが大切です。
この記事では丁寧に違いと使いどころを解説します。
Pythonの割り算の基本: / と // の違い
/ は実数の割り算
/
は常に実数の割り算を行い、結果はfloat
になります。
整数同士でも例外ではありません。
計算は実数として行われるため、小数部分を持つ結果がそのまま得られます。
# / は実数の割り算。整数同士でも float が返る
a = 7 / 3
print(a, type(a)) # 2.333... と <class 'float'>
2.3333333333333335 <class 'float'>
// は切り捨ての整数割り算
//
は床関数(小数点以下を切り捨て)に相当する割り算です。
数学的にはfloor(a / b)
に一致し、負の方向(−∞側)に丸めるのがポイントです。
# // は床(小数点以下切り捨て)。負の方向へ丸める
print(7 // 3) # 2
print(-7 // 3) # -3 に注意 (負の方向へ)
2
-3
結果の型は intかfloat
//
の結果の型はオペランドに依存します。
両方がint
ならint、どちらかがfloat
ならfloatです。
一方/
は必ずfloat
を返します。
print(7 // 3, type(7 // 3)) # 2 <class 'int'>
print(7.0 // 3, type(7.0 // 3)) # 2.0 <class 'float'>
print(7 / 3, type(7 / 3)) # 2.333... <class 'float'>
2 <class 'int'>
2.0 <class 'float'>
2.3333333333333335 <class 'float'>
- 関連記事:変数の使い方完全入門
以下に違いを整理します。
演算子 | 意味 | 丸め方向 | 主な戻り値の型 | 例 |
---|---|---|---|---|
/ | 実数の割り算 | 丸めなし | float | 7/3 -> 2.3333... |
// | 床(切り捨て)割り算 | −∞方向へ丸め | オペランドに依存 | -7//3 -> -3 |
負の数の//
は直感とズレやすいため、以降で詳しく見ていきます。
正の数での挙動と例
7/3 の結果
print(7 / 3) # 実数の割り算
2.3333333333333335
7//3 の結果
print(7 // 3) # 正の数なので単純に 2
2
floatを含む // の結果
どちらかがfloat
なら//
の戻り値もfloat
です。
結果の数値自体は同じでも、型が異なる点に注意します。
print(7.0 // 3) # 2.0 (float)
print(7 // 3.0) # 2.0 (float)
2.0
2.0
負の数の切り捨てと注意点
-7//3 が -3 になる理由
//
は床(−∞方向)に丸めるため、-7/3
の実数結果(約-2.333…)をさらに小さい方向へ丸め、-3
になります。
print(-7 / 3) # 実数の結果は -2.333...
print(-7 // 3) # 床(−∞方向)に丸めて -3 になる
-2.3333333333333335
-3
int(a/b) と // の違い
int(x)
は0方向への切り捨て(丸め)です。
一方//
は−∞方向です。
負の数で結果が異なります。
# int(a/b) は 0 方向(小数点以下を単純に捨てる)
print(int(-7 / 3)) # -2 (0 に近づく)
# // は -∞ 方向
print(-7 // 3) # -3
-2
-3
0方向に寄せたいならint()
かmath.trunc()
、床に寄せたいなら//
かmath.floor()
を使います。
import math
x = -7 / 3
print("x:", x)
print("math.trunc(x):", math.trunc(x)) # 0 方向
print("math.floor(x):", math.floor(x)) # -∞ 方向
x: -2.3333333333333335
math.trunc(x): -2
math.floor(x): -3
望む丸め方向の選び方
要件が「常に下限方向に丸める(過大計上しない)」なら//
やmath.floor
を使います。
逆に「絶対に超えない最大のページ番号を出したい」なども床が適切です。
一方「符号に関係なく小数点以下を捨てたい」ならint()
やmath.trunc()
を選びます。
上方向へ切り上げたい場合はmath.ceil()
です。
実務での使い方とベストプラクティス
ページングやインデックス計算
ページングではページ数を切り上げて計算し、ページ番号やインデックスは切り捨てで求めます。
典型パターンを示します。
# 総件数 total と 1ページ件数 per_page から総ページ数を出す(切り上げ)
total = 53
per_page = 10
# 典型: (n + d - 1) // d で切り上げ (整数同士なので結果は int)
total_pages = (total + per_page - 1) // per_page
print("総ページ数:", total_pages) # 6
# 0始まりの item_index を 0始まりの page_index に変換(切り捨て)
item_index = 27
page_index = item_index // per_page # 0-based
print("0始まりページ番号:", page_index) # 2
# 1始まりが必要なら +1 する
page_number = page_index + 1 # 1-based
print("1始まりページ番号:", page_number) # 3
総ページ数: 6
0始まりページ番号: 2
1始まりページ番号: 3
要件が1始まりか0始まりか、端数の扱いは切り上げか切り捨てかを、最初に明確にしてから式を設計します。
端数処理の要件を確認
実務では、丸め方向の取り違いが不具合の原因になります。
代表的な要件と対応をまとめます。
要件 | 適切な手段 | 例 |
---|---|---|
常に下方向へ(過大計上しない) | // または math.floor | 在庫を箱数に換算 |
常に0方向へ(符号に依らず小数点以下を捨てる) | int() または math.trunc | 金額の端数カット |
常に上方向へ(不足を許さない) | math.ceil または (n+d-1)//d | ページ数、箱数の必要数 |
四捨五入 | round | 表示用の数値整形 |
丸め規則が未定のままコーディングするのは禁物です。
仕様を先に確定しましょう。
floatでの // と丸め誤差
浮動小数点の誤差により、//
の結果が期待より小さくなることがあります。
たとえば0.3/0.1
は内部表現の都合でぴったり3にならず、床で2になります。
print(0.3 / 0.1) # 期待は 3.0 だが、実際は 2.9999999999999996
print(0.3 // 0.1) # 床を取るため 2.0 になってしまう
2.9999999999999996
2.0
金額など誤差を許せない場面ではdecimal.Decimal
の使用を検討します。
from decimal import Decimal, getcontext
getcontext().prec = 28 # 十分な精度を設定
a = Decimal("0.3")
b = Decimal("0.1")
print(a / b) # 正確に 3
print(a // b) # 正確に 3
3
3
float同士の//
は誤差を床で拾ってしまうため特に注意してください。
可能なら整数(スケーリング)かDecimal
を使います。
読みやすさを保つ書き方
可読性はバグ低減につながります。
以下の点を心がけます。
過度なテクニックを避け、意図を明確に表現します。
n = 12
s = 5
# NG: 意図が読み取りづらい
pages = n + s - 1 // s # 演算子の優先順位ミスの温床
# OK: 括弧で意図を明確化
pages = (n + s - 1) // s
# 型の混在を避ける (必要なら明示的に型変換)
items = 53
per_page = 10.0
# NG: float を不要に混在させてしまう
print(items // per_page) # 2.0 ... 型が float になる
# OK: 整数で扱えるなら整数で
print(items // int(per_page)) # 5
# PEP 8: 演算子の前後にスペースを入れて読みやすく
count_per_box = 12
boxes = (items + count_per_box - 1) // count_per_box
5.0
5
- 関連記事:コーディング規約PEP8の書き方まとめ
まとめ
/
は実数の割り算で常にfloat
、//
は床(−∞方向)への切り捨てでオペランド次第でint
またはfloat
になります。
正の数では直感通りでも、負の数では-7//3 == -3
のように結果が変わる点に注意が必要です。
ページングやインデックス計算では//
が有効ですが、floatの誤差を伴う//
は危険です。
整数化やDecimal
を用い、丸め方向の要件(床・0方向・天井・四捨五入)を事前に確認して、読みやすい式で安全に実装しましょう。