閉じる

Pythonの/と//の違いは?整数割り算を切り捨てる書き方

Pythonで割り算を書くとき、///はまったく別物です。

前者は実数の割り算、後者は小数点以下を切り捨てる割り算です。

特に負の数では結果が直感と違うことがあるため、丸め方向と結果の型を理解してから使うことが大切です。

この記事では丁寧に違いと使いどころを解説します。

Pythonの割り算の基本: / と // の違い

/ は実数の割り算

/は常に実数の割り算を行い、結果はfloatになります。

整数同士でも例外ではありません。

計算は実数として行われるため、小数部分を持つ結果がそのまま得られます。

Python
# / は実数の割り算。整数同士でも float が返る
a = 7 / 3
print(a, type(a))  # 2.333... と <class 'float'>
実行結果
2.3333333333333335 <class 'float'>

// は切り捨ての整数割り算

//床関数(小数点以下を切り捨て)に相当する割り算です。

数学的にはfloor(a / b)に一致し、負の方向(−∞側)に丸めるのがポイントです。

Python
# // は床(小数点以下切り捨て)。負の方向へ丸める
print(7 // 3)    # 2
print(-7 // 3)   # -3 に注意 (負の方向へ)
実行結果
2
-3

結果の型は intかfloat

//の結果の型はオペランドに依存します。

両方がintならint、どちらかがfloatならfloatです。

一方/は必ずfloatを返します。

Python
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'>

以下に違いを整理します。

演算子意味丸め方向主な戻り値の型
/実数の割り算丸めなしfloat7/3 -> 2.3333...
//床(切り捨て)割り算−∞方向へ丸めオペランドに依存-7//3 -> -3

負の数の//は直感とズレやすいため、以降で詳しく見ていきます。

正の数での挙動と例

7/3 の結果

Python
print(7 / 3)  # 実数の割り算
実行結果
2.3333333333333335

7//3 の結果

Python
print(7 // 3)  # 正の数なので単純に 2
実行結果
2

floatを含む // の結果

どちらかがfloatなら//の戻り値もfloatです。

結果の数値自体は同じでも、型が異なる点に注意します。

Python
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になります。

Python
print(-7 / 3)   # 実数の結果は -2.333...
print(-7 // 3)  # 床(−∞方向)に丸めて -3 になる
実行結果
-2.3333333333333335
-3

int(a/b) と // の違い

int(x)は0方向への切り捨て(丸め)です。

一方//は−∞方向です。

負の数で結果が異なります。

Python
# int(a/b) は 0 方向(小数点以下を単純に捨てる)
print(int(-7 / 3))  # -2 (0 に近づく)
# // は -∞ 方向
print(-7 // 3)      # -3
実行結果
-2
-3

0方向に寄せたいならint()math.trunc()、床に寄せたいなら//math.floor()を使います。

Python
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()です。

実務での使い方とベストプラクティス

ページングやインデックス計算

ページングではページ数を切り上げて計算し、ページ番号やインデックスは切り捨てで求めます。

典型パターンを示します。

Python
# 総件数 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になります。

Python
print(0.3 / 0.1)   # 期待は 3.0 だが、実際は 2.9999999999999996
print(0.3 // 0.1)  # 床を取るため 2.0 になってしまう
実行結果
2.9999999999999996
2.0

金額など誤差を許せない場面ではdecimal.Decimalの使用を検討します。

Python
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を使います。

読みやすさを保つ書き方

可読性はバグ低減につながります。

以下の点を心がけます。

過度なテクニックを避け、意図を明確に表現します。

Python
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

まとめ

/は実数の割り算で常にfloat//は床(−∞方向)への切り捨てでオペランド次第でintまたはfloatになります。

正の数では直感通りでも、負の数では-7//3 == -3のように結果が変わる点に注意が必要です。

ページングやインデックス計算では//が有効ですが、floatの誤差を伴う//は危険です。

整数化やDecimalを用い、丸め方向の要件(床・0方向・天井・四捨五入)を事前に確認して、読みやすい式で安全に実装しましょう。

この記事を書いた人
エーテリア編集部
エーテリア編集部

人気のPythonを初めて学ぶ方向けに、文法の基本から小さな自動化まで、実際に手を動かして理解できる記事を書いています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!