可能重复:
C ++操作符%的保证
在C ++ 98/03
5.6-4
二进制/操作员产生的商,和二进制%操作者产生了由第二所述第一表达的除法的余数。 如果/或%所述第二操作数是零的行为是未定义; 否则(A / B)* B + A%b等于一个。 如果两个操作数都是非负,则剩余部分非负; 如果没有,其余的标志是实现定义的 。
在C + + 11:
5.6 -4
二进制/操作员产生的商,和二进制%操作者产生了由第二所述第一表达的除法的余数。 如果/或%所述第二操作数是零的行为是未定义。 对于整型操作数/运算产生具有丢弃任何小数部分代数商; 81如果商A / B为在结果,(A / B)* B + A%b等于一个的类型表示的。
正如你所看到的实现定义为符号位丢失,会发生什么呢?
的行为%
的收紧在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 - f
。 a
可以被扩展为(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)
该算法说(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) = 0
和b
是负的,那么,它会被抵消时,它的的产物0
。
因此,只有迹象a
确定的符号f(a,b)
或a%b
。