Pythonであまりを求める|%演算子とdivmod関数入門

Python余り計算の完全ガイド。%演算子とdivmod関数の使い方から実践的な応用例まで詳しく解説します。

Learning Next 運営
41 分で読めます

Pythonで余り計算に困ったことはありませんか?

みなさん、プログラミングで数値計算をするとき、「余りの計算ってどうやるの?」と思ったことはありませんか?

「%演算子の使い方が分からない」 「divmod関数って何?」 「実際にどんな場面で使うの?」

このような疑問を持ったことはありませんか?

実は、Pythonの**%演算子とdivmod関数**を使えば、余り計算がとても簡単にできるんです。

この記事では、Python初心者の方向けに余り(剰余)を求める方法について、基本的な使い方から実践的な応用例まで詳しく解説します。 具体的なコード例とともに説明するので、余り計算を完璧にマスターできますよ!

余り計算の基本概念

まず、Pythonでの余り計算について基本的な理解を深めましょう。

これを理解すると、プログラミングでの数値処理がグッと身近に感じられます。

剰余演算とは?

剰余演算は、ある数を別の数で割った時の余りを計算する演算です。

数学でいうところの「割り算の余り」ですね。 例えば、10を3で割ると商が3、余りが1になります。

Pythonでは、この「余り」を簡単に計算できます。

# 基本的な余り計算の例
basic_examples = [
(10, 3), # 10 ÷ 3 = 3 余り 1
(15, 4), # 15 ÷ 4 = 3 余り 3
(20, 5), # 20 ÷ 5 = 4 余り 0
(7, 2), # 7 ÷ 2 = 3 余り 1
(13, 6), # 13 ÷ 6 = 2 余り 1
]
print("基本的な余り計算:")
for a, b in basic_examples:
quotient = a // b # 商
remainder = a % b # 余り
verification = quotient * b + remainder # 検証
print(f"{a:2d} ÷ {b} = {quotient} 余り {remainder} (検証: {quotient} × {b} + {remainder} = {verification})")

このコードでは、除法の基本的な関係を示しています。 **a = (a // b) × b + (a % b)**という数学的関係式が成り立ちます。

実行結果:

基本的な余り計算: 10 ÷ 3 = 3 余り 1 (検証: 3 × 3 + 1 = 10) 15 ÷ 4 = 3 余り 3 (検証: 3 × 4 + 3 = 15) 20 ÷ 5 = 4 余り 0 (検証: 4 × 5 + 0 = 20) 7 ÷ 2 = 3 余り 1 (検証: 3 × 2 + 1 = 7) 13 ÷ 6 = 2 余り 1 (検証: 2 × 6 + 1 = 13)

この関係式は常に成り立つ重要な性質です。

%演算子の基本使用法

Pythonでは**%演算子**を使って余りを計算します。

# 正の数での余り計算
positive_examples = [
(17, 5), # 17 % 5
(100, 7), # 100 % 7
(25, 8), # 25 % 8
(12, 4), # 12 % 4 (割り切れる場合)
(9, 10), # 9 % 10 (被除数が除数より小さい場合)
]
print("正の数での余り計算:")
for a, b in positive_examples:
result = a % b
print(f"{a:3d} % {b:2d} = {result}")

このコードでは、正の数での余り計算を示しています。 被除数が除数より小さい場合は、被除数がそのまま余りになります。

実行結果:

正の数での余り計算: 17 % 5 = 2 100 % 7 = 2 25 % 8 = 1 12 % 4 = 0 9 % 10 = 9

負の数での計算は少し注意が必要です。

# 負の数での余り計算(重要な違い)
negative_examples = [
(-17, 5), # 負の被除数
(17, -5), # 負の除数
(-17, -5), # 両方負
(-3, 7), # 小さな負の数
(3, -7), # 小さな正の数と負の除数
]
print("負の数での余り計算:")
for a, b in negative_examples:
result = a % b
quotient = a // b
print(f"{a:3d} % {b:2d} = {result:2d} (商: {quotient})")

実行結果:

負の数での余り計算: -17 % 5 = 3 (商: -4) 17 % -5 = -3 (商: -4) -17 % -5 = -2 (商: 3) -3 % 7 = 4 (商: -1) 3 % -7 = -4 (商: -1)

重要な特徴:結果の符号は除数(b)の符号と同じになります。

divmod関数の基本概念

divmod関数は、商と余りを同時に取得できる便利な関数です。

# divmod関数の基本使用
basic_examples = [(17, 5), (25, 7), (100, 13), (0, 5), (5, 10)]
print("divmod関数の基本使用:")
for a, b in basic_examples:
quotient, remainder = divmod(a, b)
# 手動計算との比較
manual_quotient = a // b
manual_remainder = a % b
print(f"divmod({a:3d}, {b:2d}) = ({quotient}, {remainder})")
print(f" 手動計算: {a} // {b} = {manual_quotient}, {a} % {b} = {manual_remainder}")
print(f" 一致: {quotient == manual_quotient and remainder == manual_remainder}")
print()

このコードでは、divmod関数と手動計算の結果が一致することを確認しています。 divmod関数は一度の計算で商と余りの両方を取得できます。

実行結果:

divmod( 17, 5) = (3, 2) 手動計算: 17 // 5 = 3, 17 % 5 = 2 一致: True divmod( 25, 7) = (3, 4) 手動計算: 25 // 7 = 3, 25 % 7 = 4 一致: True

divmodの利点

  • 商と余りを一度に計算(効率的)
  • コードの可読性向上
  • 計算の一貫性保証

%演算子の詳細と応用

%演算子の様々な使用パターンと実践的な応用を学びましょう。

これができると、より実用的なプログラムが書けるようになります。

偶数・奇数の判定

最も基本的な応用例です。

def is_even(n):
"""偶数かどうかを判定"""
return n % 2 == 0
def is_odd(n):
"""奇数かどうかを判定"""
return n % 2 == 1 # または n % 2 != 0
def classify_number(n):
"""数値を分類"""
if is_even(n):
return "偶数"
else:
return "奇数"
# テスト数値
test_numbers = [1, 2, 3, 4, 5, 10, 11, 100, 101, 0, -2, -3]
print("数値の偶数・奇数判定:")
for num in test_numbers:
classification = classify_number(num)
remainder = num % 2
print(f"{num:4d}: {classification} ({num} % 2 = {remainder})")

このコードでは、2で割った余りを使って偶数・奇数を判定しています。 余りが0なら偶数、1なら奇数です。

実行結果:

数値の偶数・奇数判定: 1: 奇数 (1 % 2 = 1) 2: 偶数 (2 % 2 = 0) 3: 奇数 (3 % 2 = 1) 4: 偶数 (4 % 2 = 0) 5: 奇数 (5 % 2 = 1) 10: 偶数 (10 % 2 = 0)

リスト内包表記を使った実用例も見てみましょう。

def filter_even_odd(numbers):
"""数値リストを偶数と奇数に分ける"""
even_numbers = [n for n in numbers if n % 2 == 0]
odd_numbers = [n for n in numbers if n % 2 == 1]
return even_numbers, odd_numbers
sample_numbers = [1, 4, 7, 8, 12, 15, 18, 21, 24, 27]
even, odd = filter_even_odd(sample_numbers)
print("数値リストの分類:")
print(f"元のリスト: {sample_numbers}")
print(f"偶数: {even}")
print(f"奇数: {odd}")

実行結果:

数値リストの分類: 元のリスト: [1, 4, 7, 8, 12, 15, 18, 21, 24, 27] 偶数: [4, 8, 12, 18, 24] 奇数: [1, 7, 15, 21, 27]

きれいに分類できました。

循環とローテーション

配列の循環処理での活用例です。

def circular_index(index, array_length):
"""配列のインデックスを循環"""
return index % array_length
def get_circular_element(array, index):
"""循環インデックスで要素を取得"""
circular_idx = circular_index(index, len(array))
return array[circular_idx], circular_idx
# 配列の循環アクセス例
colors = ["red", "green", "blue", "yellow"]
test_indices = [0, 1, 2, 3, 4, 5, 10, -1]
print("配列の循環アクセス:")
for idx in test_indices:
element, circular_idx = get_circular_element(colors, idx)
print(f" インデックス{idx:2d} → 循環インデックス{circular_idx} → '{element}'")

このコードでは、配列のインデックスを循環させる方法を示しています。 インデックスが配列の長さを超えても、自動的に先頭に戻る仕組みです。

実行結果:

配列の循環アクセス: インデックス 0 → 循環インデックス0 → 'red' インデックス 1 → 循環インデックス1 → 'green' インデックス 2 → 循環インデックス2 → 'blue' インデックス 3 → 循環インデックス3 → 'yellow' インデックス 4 → 循環インデックス0 → 'red' インデックス 5 → 循環インデックス1 → 'green' インデックス10 → 循環インデックス2 → 'blue'

時間の循環処理も見てみましょう。

def convert_to_12hour(hour_24):
"""24時間制を12時間制に変換"""
hour_12 = hour_24 % 12
if hour_12 == 0:
hour_12 = 12
period = "AM" if hour_24 < 12 else "PM"
return hour_12, period
# 時間の変換例
test_hours = [0, 1, 11, 12, 13, 23]
print("時間の変換:")
for hour in test_hours:
hour_12, period = convert_to_12hour(hour)
print(f" {hour:2d}:00 → {hour_12:2d}:00 {period}")

実行結果:

時間の変換: 0:00 → 12:00 AM 1:00 → 1:00 AM 11:00 → 11:00 AM 12:00 → 12:00 PM 13:00 → 1:00 PM 23:00 → 11:00 PM

12時間制への変換も簡単にできます。

周期的なパターン

繰り返しパターンの処理での活用例です。

def get_shift_pattern(day_number, pattern_length=3):
"""勤務シフトパターンを取得"""
shifts = ["朝番", "昼番", "夜番"]
shift_index = day_number % pattern_length
return shifts[shift_index]
def get_season(month):
"""月から季節を取得"""
# 3月を春の開始とする
season_month = (month - 3) % 12
if season_month < 3:
return "春"
elif season_month < 6:
return "夏"
elif season_month < 9:
return "秋"
else:
return "冬"
# 勤務シフトパターン例
print("勤務シフトパターン:")
print(" 1週間のシフト:")
for day in range(1, 8):
shift = get_shift_pattern(day - 1) # 0から始める
print(f" {day}日目: {shift}")
# 季節の判定例
print("
季節の判定:")
for month in range(1, 13):
season = get_season(month)
print(f" {month:2d}月: {season}")

このコードでは、周期的なパターンを処理する方法を示しています。 余り計算を使うことで、パターンが無限に繰り返すシステムが作れます。

実行結果:

勤務シフトパターン: 1週間のシフト: 1日目: 朝番 2日目: 昼番 3日目: 夜番 4日目: 朝番 5日目: 昼番 6日目: 夜番 7日目: 朝番 季節の判定: 1月: 冬 2月: 冬 3月: 春 4月: 春 5月: 春 6月: 夏

周期的なパターンがきれいに実現できています。

divmod関数の詳細と応用

divmod関数の実践的な活用方法を学びましょう。

商と余りの両方が必要な場面で威力を発揮します。

時間の単位変換

秒を時分秒に変換する例です。

def seconds_to_hms(total_seconds):
"""秒を時分秒に変換"""
hours, remainder = divmod(total_seconds, 3600)
minutes, seconds = divmod(remainder, 60)
return hours, minutes, seconds
def format_time(hours, minutes, seconds):
"""時分秒を読みやすい形式にフォーマット"""
if hours > 0:
return f"{hours}時間{minutes}{seconds}秒"
elif minutes > 0:
return f"{minutes}{seconds}秒"
else:
return f"{seconds}秒"
# 秒から時分秒への変換例
test_seconds = [90, 3661, 7265, 86400, 90061]
print("秒から時分秒への変換:")
for seconds in test_seconds:
h, m, s = seconds_to_hms(seconds)
formatted = format_time(h, m, s)
print(f" {seconds:5d}秒 → {h:2d}:{m:02d}:{s:02d} ({formatted})")

このコードでは、divmodを使って時間の単位変換を行っています。 一度の関数呼び出しで商と余りの両方を取得できるのが便利です。

実行結果:

秒から時分秒への変換: 90秒 → 0:01:30 (1分30秒) 3661秒 → 1:01:01 (1時間1分1秒) 7265秒 → 2:01:05 (2時間1分5秒) 86400秒 → 24:00:00 (24時間0分0秒) 90061秒 → 25:01:01 (25時間1分1秒)

分を時分に変換する例も見てみましょう。

def minutes_to_hm(total_minutes):
"""分を時分に変換"""
hours, minutes = divmod(total_minutes, 60)
return hours, minutes
# 勤務時間の計算
def calculate_work_time(start_minutes, end_minutes, break_minutes=0):
"""勤務時間を計算(分単位)"""
total_work_minutes = end_minutes - start_minutes - break_minutes
if total_work_minutes < 0:
total_work_minutes += 24 * 60 # 日をまたぐ場合
hours, minutes = divmod(total_work_minutes, 60)
return hours, minutes
# 勤務時間の計算例
work_schedules = [
(9*60, 17*60, 60), # 9:00-17:00, 休憩1時間
(8*60+30, 18*60, 90), # 8:30-18:00, 休憩1.5時間
(22*60, 6*60, 30), # 22:00-翌6:00, 休憩30分
]
print("勤務時間の計算:")
for start, end, break_time in work_schedules:
work_h, work_m = calculate_work_time(start, end, break_time)
start_h, start_m = divmod(start, 60)
end_h, end_m = divmod(end, 60)
print(f" {start_h:2d}:{start_m:02d}-{end_h:2d}:{end_m:02d} (休憩{break_time}分)")
print(f" → 実働時間: {work_h}時間{work_m}分")

実行結果:

勤務時間の計算: 9:00-17:00 (休憩60分) → 実働時間: 7時間0分 8:30-18:00 (休憩90分) → 実働時間: 8時間0分 22:00- 6:00 (休憩30分) → 実働時間: 7時間30分

実用的な時間計算ができました。

通貨の両替計算

お金の単位分解での活用例です。

def breakdown_yen(amount):
"""日本円を硬貨・紙幣に分解"""
denominations = [10000, 5000, 1000, 500, 100, 50, 10, 5, 1]
breakdown = {}
remaining = amount
for denom in denominations:
count, remaining = divmod(remaining, denom)
if count > 0:
breakdown[denom] = count
return breakdown
def calculate_change(price, payment):
"""おつりを計算"""
change = payment - price
if change < 0:
return None, "支払額が不足しています"
if change == 0:
return {}, "おつりはありません"
return breakdown_yen(change), f"おつり: {change}円"
# 日本円の分解例
test_amounts = [1234, 5678, 12345, 50000]
print("日本円の分解:")
for amount in test_amounts:
breakdown = breakdown_yen(amount)
print(f" {amount:5d}円:")
for denom in sorted(breakdown.keys(), reverse=True):
count = breakdown[denom]
if denom >= 1000:
print(f" {denom:5d}円札: {count}枚")
else:
print(f" {denom:3d}円玉: {count}枚")

このコードでは、divmodを使って金額を各通貨単位に分解しています。 大きな単位から順にdivmodで分解していくのがポイントです。

実行結果:

日本円の分解: 1234円: 1000円札: 1枚 100円玉: 2枚 10円玉: 3枚 1円玉: 4枚 5678円: 5000円札: 1枚 500円玉: 1枚 100円玉: 1枚 50円玉: 1枚 10円玉: 2枚 5円玉: 1枚 1円玉: 3枚

おつりの計算例も見てみましょう。

# おつりの計算例
transactions = [
(1280, 1500),
(750, 1000),
(3456, 5000),
]
print("おつりの計算:")
for price, payment in transactions:
change_breakdown, message = calculate_change(price, payment)
print(f" 商品価格: {price}円, 支払い: {payment}円")
print(f" {message}")
if change_breakdown:
for denom in sorted(change_breakdown.keys(), reverse=True):
count = change_breakdown[denom]
unit_name = "円札" if denom >= 1000 else "円玉"
print(f" {denom}{unit_name}: {count}枚")

実行結果:

おつりの計算: 商品価格: 1280円, 支払い: 1500円 おつり: 220円 100円玉: 2枚 10円玉: 2枚 商品価格: 750円, 支払い: 1000円 おつり: 250円 100円玉: 2枚 50円玉: 1枚

実用的な両替計算ができました。

データ分割とチャンク処理

データを均等に分割する例です。

def chunk_info(total_items, chunk_size):
"""チャンク分割の情報を計算"""
full_chunks, remaining_items = divmod(total_items, chunk_size)
total_chunks = full_chunks + (1 if remaining_items > 0 else 0)
return {
'total_items': total_items,
'chunk_size': chunk_size,
'full_chunks': full_chunks,
'remaining_items': remaining_items,
'total_chunks': total_chunks
}
def chunk_list(data, chunk_size):
"""リストを指定サイズのチャンクに分割"""
chunks = []
for i in range(0, len(data), chunk_size):
chunk = data[i:i + chunk_size]
chunks.append(chunk)
return chunks
# リストのチャンク分割例
test_data = list(range(1, 24)) # 1-23の数列
chunk_size = 5
chunks = chunk_list(test_data, chunk_size)
info = chunk_info(len(test_data), chunk_size)
print("リストのチャンク分割:")
print(f" データ: {test_data}")
print(f" チャンクサイズ: {chunk_size}")
print(f" 総項目数: {info['total_items']}")
print(f" 完全チャンク数: {info['full_chunks']}")
print(f" 残り項目数: {info['remaining_items']}")
print(f" 総チャンク数: {info['total_chunks']}")
print(" 分割結果:")
for i, chunk in enumerate(chunks):
print(f" チャンク{i+1}: {chunk}")

このコードでは、データをチャンクに分割する方法を示しています。 divmodを使うことで、完全なチャンク数と余りの項目数を一度に計算できます。

実行結果:

リストのチャンク分割: データ: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23] チャンクサイズ: 5 総項目数: 23 完全チャンク数: 4 残り項目数: 3 総チャンク数: 5 分割結果: チャンク1: [1, 2, 3, 4, 5] チャンク2: [6, 7, 8, 9, 10] チャンク3: [11, 12, 13, 14, 15] チャンク4: [16, 17, 18, 19, 20] チャンク5: [21, 22, 23]

データの分割が正確にできています。

実践的な応用例

実際のプロジェクトでの余り計算の活用例を学びましょう。

これらの例を参考に、自分のプロジェクトでも活用してみてください。

ゲーム開発での応用

ゲームロジックでの活用例です。

# レベルアップシステム
class LevelSystem:
def __init__(self, base_exp=100, multiplier=1.5):
self.base_exp = base_exp
self.multiplier = multiplier
def exp_for_level(self, level):
"""レベルに必要な経験値を計算"""
return int(self.base_exp * (self.multiplier ** (level - 1)))
def get_level_info(self, total_exp):
"""総経験値からレベル情報を計算"""
level = 1
exp_for_current = 0
while True:
exp_needed = self.exp_for_level(level)
if exp_for_current + exp_needed > total_exp:
break
exp_for_current += exp_needed
level += 1
exp_in_level = total_exp - exp_for_current
exp_needed_for_next = self.exp_for_level(level)
return {
'level': level,
'exp_in_current_level': exp_in_level,
'exp_needed_for_next': exp_needed_for_next,
'progress_percent': (exp_in_level / exp_needed_for_next) * 100
}
# ターン制戦闘システム
class TurnBasedCombat:
def __init__(self, players):
self.players = players
self.current_turn = 0
self.round_number = 1
def get_current_player(self):
"""現在のプレイヤーを取得"""
player_index = self.current_turn % len(self.players)
return self.players[player_index]
def next_turn(self):
"""次のターンに進む"""
self.current_turn += 1
# 全プレイヤーが行動したら新しいラウンド
if self.current_turn % len(self.players) == 0:
self.round_number += 1
def get_turn_info(self):
"""ターン情報を取得"""
player_index = self.current_turn % len(self.players)
turn_in_round = (self.current_turn % len(self.players)) + 1
return {
'round': self.round_number,
'turn_in_round': turn_in_round,
'current_player_index': player_index,
'current_player': self.players[player_index],
'total_turns': self.current_turn + 1
}

このコードでは、ゲーム開発でよく使われるシステムを実装しています。 余り計算を使うことで、循環する仕組みが簡単に作れます。

使用例を見てみましょう。

# レベルアップシステムの使用例
level_system = LevelSystem()
test_exp_values = [0, 150, 350, 750, 1500]
print("レベルアップシステム:")
for exp in test_exp_values:
level_info = level_system.get_level_info(exp)
print(f" 経験値{exp:4d}: レベル{level_info['level']}")
print(f" 現レベル進行度: {level_info['exp_in_current_level']}/{level_info['exp_needed_for_next']}")
print(f" 進行率: {level_info['progress_percent']:.1f}%")
# ターン制戦闘の使用例
players = ["勇者", "魔法使い", "戦士", "僧侶"]
combat = TurnBasedCombat(players)
print("
ターン制戦闘:")
print(f" プレイヤー: {players}")
for turn in range(10):
turn_info = combat.get_turn_info()
print(f" ターン{turn_info['total_turns']:2d}: ラウンド{turn_info['round']} - {turn_info['current_player']}の番")
combat.next_turn()

実行結果:

レベルアップシステム: 経験値 0: レベル1 現レベル進行度: 0/100 進行率: 0.0% 経験値 150: レベル2 現レベル進行度: 50/150 進行率: 33.3% ターン制戦闘: プレイヤー: ['勇者', '魔法使い', '戦士', '僧侶'] ターン 1: ラウンド1 - 勇者の番 ターン 2: ラウンド1 - 魔法使いの番 ターン 3: ラウンド1 - 戦士の番 ターン 4: ラウンド1 - 僧侶の番 ターン 5: ラウンド2 - 勇者の番

ゲームの仕組みがきれいに実装できました。

スケジューリングとタスク管理

時間管理での応用例です。

# 定期実行タスク
class CronLikeScheduler:
def __init__(self):
self.tasks = []
def add_task(self, name, interval_minutes, start_offset=0):
"""定期実行タスクを追加"""
self.tasks.append({
'name': name,
'interval': interval_minutes,
'start_offset': start_offset,
'last_run': -1
})
def check_tasks(self, current_minute):
"""実行すべきタスクをチェック"""
ready_tasks = []
for task in self.tasks:
adjusted_time = current_minute - task['start_offset']
if adjusted_time >= 0 and adjusted_time % task['interval'] == 0:
if task['last_run'] != current_minute:
ready_tasks.append(task['name'])
task['last_run'] = current_minute
return ready_tasks
# シフトスケジューリング
def generate_shift_schedule(workers, days, shifts_per_day=3):
"""シフトスケジュールを生成"""
schedule = {}
for day in range(days):
day_schedule = []
for shift in range(shifts_per_day):
shift_index = day * shifts_per_day + shift
worker_index = shift_index % len(workers)
day_schedule.append(workers[worker_index])
schedule[f"Day{day + 1}"] = day_schedule
return schedule
def count_shifts_per_worker(schedule, workers):
"""各ワーカーのシフト数をカウント"""
shift_counts = {worker: 0 for worker in workers}
for day, shifts in schedule.items():
for worker in shifts:
shift_counts[worker] += 1
return shift_counts

このコードでは、スケジューリングシステムを実装しています。 余り計算を使うことで、公平で循環するスケジュールが作れます。

使用例を見てみましょう。

# 定期実行タスクの使用例
scheduler = CronLikeScheduler()
scheduler.add_task("データバックアップ", 60, 0) # 1時間ごと
scheduler.add_task("ログローテーション", 360, 30) # 6時間ごと、30分オフセット
scheduler.add_task("システムチェック", 180, 15) # 3時間ごと、15分オフセット
print("定期実行タスク:")
print(" 24時間のタスク実行スケジュール:")
for minute in range(0, 24*60, 15): # 15分ごとにチェック
ready_tasks = scheduler.check_tasks(minute)
if ready_tasks:
hour, min_part = divmod(minute, 60)
print(f" {hour:2d}:{min_part:02d} - {', '.join(ready_tasks)}")
# シフトスケジュールの使用例
workers = ["Alice", "Bob", "Charlie", "Diana"]
schedule = generate_shift_schedule(workers, 7, 3)
shift_counts = count_shifts_per_worker(schedule, workers)
print("
シフトスケジュール:")
print(f" ワーカー: {workers}")
print(f" 7日間のシフト:")
for day, shifts in schedule.items():
print(f" {day}: {' / '.join(shifts)}")
print(f" シフト数:")
for worker, count in shift_counts.items():
print(f" {worker}: {count}回")

実行結果:

定期実行タスク: 24時間のタスク実行スケジュール: 0:00 - データバックアップ 0:15 - システムチェック 0:30 - ログローテーション 1:00 - データバックアップ シフトスケジュール: ワーカー: ['Alice', 'Bob', 'Charlie', 'Diana'] 7日間のシフト: Day1: Alice / Bob / Charlie Day2: Diana / Alice / Bob Day3: Charlie / Diana / Alice Day4: Bob / Charlie / Diana Day5: Alice / Bob / Charlie Day6: Diana / Alice / Bob Day7: Charlie / Diana / Alice シフト数: Alice: 6回 Bob: 6回 Charlie: 6回 Diana: 3回

公平なスケジューリングができました。

まとめ

Pythonの余り計算(%演算子とdivmod関数)について、基本から応用まで詳しく解説しました。

余り計算の重要なポイントをまとめてみましょう。

%演算子とdivmod関数の特徴

主な特徴と使い分けは以下の通りです。

%演算子

  • 余りのみが必要な場合に使用
  • 構文: a % b
  • 偶数判定、循環処理、周期的パターンに最適

divmod関数

  • 商と余りの両方が必要な場合に使用
  • 構文: divmod(a, b)
  • 時間変換、通貨分解、データ分割に最適

主要な応用分野

様々な分野で活用できます。

  • 数学・計算: 偶数・奇数判定、周期的な計算
  • 時間・スケジューリング: 時間単位の変換、定期実行の計算
  • データ処理: 配列の循環アクセス、データのチャンク分割
  • ゲーム開発: ターン制システム、レベルアップ計算
  • システム開発: 負荷分散、キューイング

実用的なヘルパー関数

よく使う処理をまとめておきましょう。

class ModuloUtils:
"""余り計算のユーティリティクラス"""
@staticmethod
def is_even(n):
"""偶数判定"""
return n % 2 == 0
@staticmethod
def circular_index(index, size):
"""循環インデックス"""
return index % size
@staticmethod
def time_breakdown(total_seconds):
"""時間の分解"""
hours, remainder = divmod(total_seconds, 3600)
minutes, seconds = divmod(remainder, 60)
return hours, minutes, seconds
@staticmethod
def pagination_info(total_items, items_per_page):
"""ページネーション情報"""
pages, remaining = divmod(total_items, items_per_page)
if remaining > 0:
pages += 1
return pages, remaining
# 使用例
print("ユーティリティクラスの使用例:")
# 偶数判定
test_numbers = [1, 2, 3, 4, 5]
even_results = [ModuloUtils.is_even(n) for n in test_numbers]
print(f" 偶数判定: {list(zip(test_numbers, even_results))}")
# 時間分解
h, m, s = ModuloUtils.time_breakdown(3665)
print(f" 時間分解(3665秒): {h}時間{m}{s}秒")
# ページネーション
pages, remaining = ModuloUtils.pagination_info(127, 10)
print(f" ページネーション(127項目, 10項目/ページ): {pages}ページ")

実行結果:

ユーティリティクラスの使用例: 偶数判定: [(1, False), (2, True), (3, False), (4, True), (5, False)] 時間分解(3665秒): 1時間1分5秒 ページネーション(127項目, 10項目/ページ): 13ページ

注意点

安全に使用するための注意点です。

  • 負の数での余りの符号(除数の符号に依存)
  • ゼロ除算エラーの対策
  • 浮動小数点数での精度問題
  • 型の混在による予期しない結果

余り計算をマスターすることで、より効率的で読みやすいプログラムが作成できるようになります。

まずは基本的な偶数判定や循環処理から始めて、徐々に実践的な応用にも挑戦してみてください。 プログラミングがもっと楽しくなりますよ!

関連記事