11

重複の可能性:
C++ 演算子 % 保証

C++ 98/03 で

5.6-4

二項 / 演算子は商を生成し、二項 % 演算子は最初の式を 2 番目の式で割った剰余を生成します。/ または % の 2 番目のオペランドがゼロの場合、動作は未定義です。それ以外の場合、(a/b)*b + a%b は a に等しくなります。両方のオペランドが負でない場合、残りは負ではありません。そうでない場合、剰余の符号は実装定義です。

C++ 11 の場合:

5.6 -4

二項 / 演算子は商を生成し、二項 % 演算子は最初の式を 2 番目の式で割った剰余を生成します。/ または % の 2 番目のオペランドがゼロの場合、動作は未定義です。整数オペランドの場合、/ 演算子は小数部分を破棄した代数商を生成します。81 商 a/b が結果の型で表現できる場合、(a/b)*b + a%b は a に等しくなります。

符号ビットの実装定義が欠落していることがわかるように、それはどうなりますか?

4

2 に答える 2

19

の動作は%C++11 で強化され、( による除算を除いて0) 完全に指定されるようになりました。

ゼロへの切り捨てと恒等の組み合わせは、が常に正の場合は正、負の場合は負で(a/b)*b + a%b == aあることを意味します。a%baa


この数学的な理由は次のとおりです。

÷を数学的除算、C /++ 除算とします。

任意の a と b について、a÷b = a/b + f(f は小数部) があり、標準から、 もあります(a/b)*b + a%b == a

a/bは に向かって切り捨てられることが知られている0ため、 が正の場合は小数部分が常にa÷b正であり、負の場合は負であることがわかっていますa÷b

sign(f) == sign(a)*sign(b)

a÷b = a/b + fを与えるように並べ替えることができますa/b = a÷b - fa次のように展開できます(a÷b)*b

(a/b)*b + a%b == a=> (a÷b - f)*b+a%b == (a÷b)*b.

左側も展開できます。

(a÷b)*b - f*b + a%b == (a÷b)*b

a%b == f*b

以前のことを思い出してくださいsign(f)==sign(a)*sign(b)

sign(a%b) == sign(f*b) == sign(a)*sign(b)*sign(b) == sign(a)

于 2012-10-27T13:57:08.603 に答える
3

アルゴリズムは と言っていますが、これは 代数(a/b)*b + a%b = aの使用 であることを覚えていれば読みやすいです。つまり、. はどのような値ですか?truncate(a/b)*b + a%b = aa%b = a - truncate(a/b)*bf(a,b) = a - truncate(a/b)*bf(a,b) < 0

bネガティブかポジティブかは関係ありません。分子と分母に現れるため、それ自体が相殺されます。truncate(a/b) = 0とが負であってもb、 の積だと相殺され0ます。

したがって、、またはaの符号を決定するのはの符号のみです。f(a,b)a%b

于 2012-10-27T14:08:22.003 に答える