11

可能重复:
C++ 运算符 % 保证

在 C++ 98/03 中

5.6-4

二元 / 运算符产生商,二元 % 运算符产生第一个表达式除以第二个表达式的余数。如果 / 或 % 的第二个操作数为零,则行为未定义;否则 (a/b)*b + a%b 等于 a。如果两个操作数都是非负数,则余数是非负数;如果不是,则余数的符号是​​ implementation-defined

在 C++ 11 中:

5.6 -4

二元 / 运算符产生商,二元 % 运算符产生第一个表达式除以第二个表达式的余数。如果 / 或 % 的第二个操作数为零,则行为未定义。对于整数操作数,/ 运算符产生代数商,其中任何小数部分被丢弃;81 如果商 a/b 可以用结果类型表示,则 (a/b)*b + a%b 等于 a。

如您所见,缺少为符号位定义的实现,它会发生什么?

4

2 回答 2

19

的行为%在 C++11 中得到了加强,现在已经完全指定(除了除以0)。

向零截断和恒等式的组合(a/b)*b + a%b == a意味着a%b对正数始终为正a,对负数始终为负a


其数学原因如下:

÷数学除法,/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 = a 使用代数,它更容易阅读,a%b = a - truncate(a/b)*b。也就是说,f(a,b) = a - truncate(a/b)*b. 价值是f(a,b) < 0什么?

不管b是消极的还是积极的。它抵消了自己,因为它出现在分子和分母中。即使truncate(a/b) = 0andb是负数,好吧,当它是 的乘积时,它也会被抵消掉0

因此,只有 的符号a决定f(a,b)或的符号a%b

于 2012-10-27T14:08:22.003 回答