同じ mod 操作を行っても、使用している言語によって結果が異なることがわかりました。
Python の場合:
-1 % 10
9を生成します
C では-1 !が生成されます。
- 正しいモジュロはどれ?
- Cでのmod操作をPythonと同じにする方法は?
((n % M) + M) % M
、Python と同じ結果が得られます。例)((-1 % 10) + 10) % 10
. 正の整数に対してどのように機能するかに注意してください: ((17 % 10) + 10) % 10 == 17 % 10
、および C 実装の両方のバリアント (正または負の剰余) に対しても同様です。Python には「真の」剰余演算がありますが、C には剰余演算があります。
これは、負の整数除算の処理方法と直接関係があります。つまり、0 または負の無限大に向かって丸められます。Python はマイナス無限大に丸め、C(99) は 0 に丸めますが、どちらの言語(n/m)*m + n%m == n
でも、% 演算子は正しい方向に補正する必要があります。
Ada はより明示的で、 と の両方を備えていmod
ますrem
。
C89/90 では、負のオペランドを持つ除算演算子と剰余演算子の動作は実装定義です。つまり、実装によっては、どちらの動作も取得できます。演算子が互いに同意することだけが必要です: froma / b = q
とa % b = r
follow a = b * q + r
. 結果に大きく依存する場合は、コードで静的アサートを使用して動作を確認します。
C99 では、観察する動作が標準になっています。
実際、どちらの動作にも特定のロジックがあります。Python の動作は、真のモジュロ演算を実装しています。あなたが観察した動作は、C が 0 への丸めと一致していることです (これは Fortran の動作でもあります)。
-a / b
C で 0 方向への丸めが好まれる理由の 1 つは、 の結果がと同じであると予想するのがむしろ自然だから-(a / b)
です。真のモジュロ動作の場合、-1 % 10
9 と評価されます。つまり、-1 / 10
-1 でなければなりません。-(1 / 10)
が 0であるため、これはかなり不自然に見えるかもしれません。
-1 modulo 10
は と同じなので、どちらの答えも正解9 modulo 10
です。
r = (a mod m)
a = n*q + r
であることは確かですが|r| < |n|
、 の値が何であるかはわかりませんr
。否定と肯定の2つの答えがあります。
C89 では、答えは常に正しいものの、モジュロ演算 (剰余と呼ばれる) の正確な値は定義されていないため、負の結果または正の結果のいずれかになる可能性があります。C99 では結果が定義されています。
ただし、肯定的な答えが必要な場合は、答えが否定的であることがわかったら、単純に 10 を足すことができます。
モジュロ演算子をすべての言語で同じように機能させるには、次のことを覚えておいてください。
n mod M == (n + M) mod M
そして一般的に:
n mod M == (n + X * M) mod M