被除数に負の数をとる場合のPythonの剰余演算規則

Pythonの剰余演算(モジュロ)で

>>>-1 % 4
3

という結果が返ってくるのはどうしてだろう?

(x // yの注)整数の除算とも呼ばれます。結果の型は整数型とは限りませんが、結果の値は整数です。結果は常に負の無限大の方向に丸められます: 1//2 は 0 、 (-1)//2 は -1 、 1//(-2) は -1 、そして (-1)//(-2) は 0 です。

% (剰余: modulo) 演算は、第一引数を第二引数で除算したときの剰余になります。数値引数はまず共通の型に変換されます。右引数値がゼロの場合には ZeroDivisionError 例外が送出されます。引数値は浮動小数点でもよく。例えば 3.14%0.7 は 0.34 になります (3.14 は 4*0.7 + 0.34 だからです)。剰余演算子は常に第二引数と同じ符号 (またはゼロ) の結果になります; 剰余演算の結果の絶対値は、常に第二引数の絶対値よりも小さくなります。

切り捨て除算演算と剰余演算は、恒等式: x == (x//y)*y + (x%y) の関係にあります。切り捨て除算や剰余はまた、組み込み関数 divmod(): divmod(x, y) == (x//y, x%y) とも関係しています。

要点は次の3つ。

負の無限大への丸めで端数処理される整数除算の影響は剰余演算にも及び、自然とその値は定まる。

-1%4の場合なら

となり、3が返されるわけだ。

剰余演算で数値をローテーション

上記規則によって、被除数が負の数でも剰余演算を利用した数のローテーションを実現できる。

>>>[i % 4 for i in range(-10, 10)]
[2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1]

参考