Cプログラムでは、以下の操作を試みていました(動作を確認するためだけに)
x = 5 % (-3);
y = (-5) % (3);
z = (-5) % (-3);
printf("%d ,%d ,%d", x, y, z);
(2, -2 , -2)
gccのように出力されました。毎回良い結果を期待していました。モジュラスが負になることはありますか? 誰でもこの動作を説明できますか?
Cプログラムでは、以下の操作を試みていました(動作を確認するためだけに)
x = 5 % (-3);
y = (-5) % (3);
z = (-5) % (-3);
printf("%d ,%d ,%d", x, y, z);
(2, -2 , -2)
gccのように出力されました。毎回良い結果を期待していました。モジュラスが負になることはありますか? 誰でもこの動作を説明できますか?
C99では、いつa/b
表現可能であるかを要求しています。
(a/b) * b
+ a%b
は等しくなければならないa
これは論理的には理にかなっています。右?
これが何につながるか見てみましょう:
例A5/(-3)
は-1
=> (-1) * (-3)
+ 5%(-3)
=5
5%(-3)
これは、が2の場合にのみ発生する可能性があります。
例B(-5)/3
は-1
=> (-1) * 3
+ (-5)%3
=-5
これは、次の場合にのみ発生する可能性(-5)%3
があります-2
%
Cの演算子はモジュロ演算子ではなく、剰余演算子です。
モジュロ演算子と剰余演算子は、負の値に関して異なります。
剰余演算子では、結果の符号は被除数 (分子) の符号と同じですが、モジュロ演算子では、結果の符号は除数 (分母) と同じです。
C では、%
操作を次のように定義してa % b
います。
a == (a / b * b) + a % b
に/
向かって切り捨てられた整数除算0
。これは、モジュロ演算子ではなく剰余演算子として0
定義する (負の無限大に向かってではなく) に向かって行われる切り捨てです。%
他の回答はC99以降で説明されています。負のオペランドを含む整数の除算は常にゼロに向かって切り捨てられます。
C89では、結果が上方向または下方向に丸められるかどうかは実装定義であることに注意してください。すべての標準で(a/b) * b + a%b
等しいため、負のオペランドを含む結果も C89 で実装定義されます。a
%
モジュロ演算の結果は分子の符号に依存するため、 yとzに対して-2が得られます。
これがリファレンスです
http://www.chemie.fu-berlin.de/chemnet/use/info/libc/libc_14.html
整数除算
このセクションでは、整数除算を実行するための関数について説明します。GNU Cでは「/」演算子は常にゼロに向かって丸められるため、これらの関数はGNUCライブラリでは冗長です。ただし、他のC実装では、「/」は負の引数で異なる方法で丸められる場合があります。divとldivは、商をゼロに丸める方法を指定するので便利です。余りは分子と同じ符号を持っています。