Pythonで、負の数に関して奇妙な動作を見つけました。
>>> -5 % 4
3
誰かが何が起こっているのか説明できますか?
CやC++とは異なり、Pythonのモジュロ演算子(%
)は常に分母(除数)と同じ符号の数値を返します。あなたの式は3をもたらします。
(-5)/ 4 = -1.25-> floor(-1.25)= -2
(-5)%4 =(-2×4 + 3)%4=3。
非負の結果がより有用であることが多いため、Cの動作よりも選択されます。例として、曜日を計算します。今日が火曜日(2日目)の場合、N日前の曜日は何日ですか?Pythonでは、次のように計算できます
return (2 - N) % 7
しかし、Cでは、N≥3の場合、無効な数である負の数を取得するため、7を追加して手動で修正する必要があります。
int result = (2 - N) % 7;
return result < 0 ? result + 7 : result;
(さまざまな言語で結果の符号がどのように決定されるかについては、http://en.wikipedia.org/wiki/Modulo_operatorを参照してください。)
Guido van Rossum からの説明は次のとおりです。
http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html
基本的に、a/b = q と剰余 r が b*q + r = a および 0 <= r < b の関係を保持するためです。
指摘したように、Python modulo は、他の言語の規則に対して十分に理由のある例外を作ります。
//
これにより、負の数にシームレスな動作が与えられます。特に、整数除算演算子と組み合わせて使用すると、%
剰余はしばしば ( math. divmodのように)使用されます。
for n in range(-8,8):
print n, n//4, n%4
プロデュース:
-8 -2 0
-7 -2 1
-6 -2 2
-5 -2 3
-4 -1 0
-3 -1 1
-2 -1 2
-1 -1 3
0 0 0
1 0 1
2 0 2
3 0 3
4 1 0
5 1 1
6 1 2
7 1 3
%
は常にゼロまたは正を出力します*//
は常に負の無限大に向かって丸めます* ... 右オペランドが正である限り。一方で11 % -10 == -9
整数の除算と負の数の mod を処理する最善の方法はありません。a/b
が と同じ大きさで符号が逆だったらいいのに(-a)/b
。a % b
本当にモジュロ b だったらいいのに。本当に が必要なa == (a/b)*b + a%b
ので、最初の 2 つは互換性がありません。
どちらを残すかは難しい問題であり、双方に議論があります。C と C++ は整数除算をゼロに丸めます (so a/b == -((-a)/b)
) が、明らかに Python はそうではありません。
モジュロ、4 の等価クラス:
これは、負の数を使用したモジュロの動作へのリンクです。(はい、ググってみました)
私もPythonの変な振る舞いだと思いました。除算を(紙の上で)うまく解けていないことがわかりました。商に 0 の値を与え、剰余に -5 の値を与えていました。ひどい... 整数の幾何学的表現を忘れていました。数直線で与えられた整数の幾何学を思い出すことで、商と剰余の正しい値を取得し、Python の動作が正常であることを確認できます。(とはいえ、あなたの懸念はかなり前に解決されていると思いますが)。
Python の除算も C とは異なることにも言及する価値があります。
>>> x = -10
>>> y = 37
Cでは、結果が期待されます
0
Pythonのx/yとは何ですか?
>>> print x/y
-1
% はモジュロです - 剰余ではありません! 一方、C の x%y は生成されます
-10
python が得られます。
>>> print x%y
27
Cのように両方を取得できます
分裂:
>>> from math import trunc
>>> d = trunc(float(x)/y)
>>> print d
0
そして残り(上記の除算を使用):
>>> r = x - d*y
>>> print r
-10
この計算はおそらく最速ではありませんが、x と y の任意の符号の組み合わせに対して機能し、C と同じ結果を達成し、さらに条件ステートメントを回避します。