-2
数学的に正しい答えは両方の場合であるため、次の理由を説明してください。
int a=7%-5; //Assigns 2 to a
int a=-7%5; //Assigns -2 to a
コードは C です。
7 / -5 = -1
余り2
ありますので-1 * -5 + 2 = 5 + 2 = 7
。
-7 / 5 = -1
余り-2
ありますので-1 * 5 + (-2) = -5 - 2 = -7
。
%
C++ では、剰余演算子です (正の数の場合、数学モジュロ演算子として機能します)。
ほとんどの C 実装では、整数除算は切り捨てられ、負の無限大に向かって丸められないためです。あなたの実装もこれらの1つのようです。
a % b = a - (a / b) * b
それで
7 % (-5) = 7 - (7 / -5) * (-5)
これは
7 % (-5) = 7 - (-1) * (-5) = 7 - 5 = 2
答えは数学的なものではなく、慣習的なものです。理論的には、モジュロ演算子には常に、負と正の 2 つの可能な結果があります。
7 % 5
またはのいずれ2
か-3
です。
数学では、主に正の結果が使用されます。プログラミング言語に依存するプログラミング。
元の C では、どちらを使用するかは指定されていません。正の数を使用すると、常に正のモジュラが得られます。負の数の場合、結果は使用するコンパイラによって異なります。
C-99 では、剰余の結果は被除数と同じ符号を持つ必要があると指定されています。それはあなたが観察する行動を説明しています。
ここで、さまざまなプログラミング言語でのモジュロ演算子の結果を確認できます。
ルールはr = a - (a/b) * b
そう
2 = 7 - (7/-5)*(-5) // note: 7/-5 is -1
IT では、負の値を使用した剰余演算には単一の定義がありません。3 つの異なるアルゴリズムがあります。
オペランドが正の場合は同じ結果を返しますが、負の場合は結果が異なります。
多くの実装では、商が切り捨て q = trunc(a/n) によって定義される切り捨て除算を使用します。つまり、正確な有理商から 0 の方向にある最初の整数であり、r=a − n q による剰余です。 . 非公式に言えば、商は「ゼロに向かって丸められる」ため、剰余は被除数と同じ符号になります。
Knuth は、商がフロア関数 q=floor(a/n) によって定義され、剰余 r が
r = a - nq = a - n \left\lfloor {a \over n} \right\rfloor.
ここで、商は常に (既に負の値であっても) 切り捨てられ、剰余は除数と同じ符号になります。
Raymond T. Boute は、剰余が常に正または 0 であるユークリッドの定義を導入したため、除算アルゴリズムと一致します (ユークリッド除算を参照)。この定義は、表では「常にポジティブ」とマークされています。q を a と n の整数商とすると、次のようになります。
C では、問題はアルゴリズムが実装定義であるため、プログラムを移植可能にしたい場合は、負の数に対して独自のモジュロ演算をロールバックする必要があることです。