Code Fix

中級

剰余演算 % の符号がJavaと異なる理由

Pythonの%は除数の符号に合わせた結果を返します。Javaなど多くの言語は被除数の符号に合わせるため、負の数を扱うと結果が変わります。

なぜエラーが出ないのか

出力: 1
(エラーなし)
Pythonは何も報告しません。文法として正しいためです
出力: 1
実際の挙動 — 期待した結果と食い違っている箇所
見つけ方
エラーが出ないので、出力を目で確かめるしかありません。この種の誤りが最も発見が遅れます

このエラーが出る典型パターン

パターン1

 1  x = -7
 2  y = 3
 3  remainder = abs(x) % y
                     ^
 4  print(remainder)
出力: 1期待: 2 (エラーにはなりません)

Pythonの%は除数の符号に合わせた結果を返します。abs()で絶対値にしてから計算すると、その正しい挙動を壊してしまいます。

直し方: abs(x) % y を x % y にします。

この問題を解いてみる →

広告
広告スロット(未設定)

パターン2

 1  day = -3
 2  remainder = abs(day) % 7
                      ^
 3  print(remainder)
出力: 3期待: 4 (エラーにはなりません)

曜日を7で割った余りで表す場合も同じです。絶対値を取ってから割ると、負の日付が表す「巻き戻り」の意味が失われます。

直し方: abs(day) % 7 を day % 7 にします。

この問題を解いてみる →

パターン3

 1  hour = -2
 2  remainder = abs(hour) % 24
                       ^
 3  print(remainder)
出力: 2期待: 22 (エラーにはなりません)

24時間表記の巻き戻り計算でも同様です。Pythonの%はそのまま使えば正しく巻き戻ってくれるので、絶対値を取る必要はありません。

直し方: abs(hour) % 24 を hour % 24 にします。

この問題を解いてみる →

パターン4

 1  index = -1
 2  size = 5
 3  pos = abs(index) % size
                  ^
 4  print(pos)
出力: 1期待: 4 (エラーにはなりません)

末尾からの位置を表す負の添字の計算でも、abs()を挟むと本来欲しい「末尾から何番目か」という値が壊れます。

直し方: abs(index) % size を index % size にします。

この問題を解いてみる →

パターン5

 1  step = -10
 2  cycle = 6
 3  phase = abs(step) % cycle
                    ^
 4  print(phase)
出力: 4期待: 2 (エラーにはなりません)

周期的な巻き戻り計算でも同様です。絶対値を取ってから割ると、負の方向へ進んだ分の意味が失われます。

直し方: abs(step) % cycle を step % cycle にします。

この問題を解いてみる →

よくある誤解

他言語の経験から「結果は負になるはず」と考え、abs()で絶対値に変換してから計算すると、Pythonが本来返す正しい結果を壊してしまいます。

実務での勘所

この設計にはPython特有の実用上のメリットもあります。循環的な添字計算(index % len(items))をするとき、indexが負の値になってもPythonの%は常に0以上除数未満の結果を返すため、そのままlistの添字として使える都合の良い性質があります。Javaのように%が被除数の符号に合わせる言語では、負のindexを使うと%の結果も負になってしまい、そのままでは添字として使えず(index % len + len) % lenのような補正が別途必要になります。

演習をはじめる

関連するエラー

広告
広告スロット(未設定)