求模,求余
%%%
计算机系统结构的GCD法引发的深思
求模与求余的区别
这是我们小学二年级就会的除法运算。
$
\begin{aligned}
5\div3&=1\cdots2\\
(-5)\div3&=(-1)\cdots(-2)\\
(-5)\div(-3)&=1\cdots(-2)\\
5\div(-3)&=(-1)\cdots2
\end{aligned}
$
数学定义
求模和求余的主要区别在于处理负数的方式。
首先,商的符号永远由被除数和除数一起决定。
- 求余操作 (a % b):
- 余数的符号与被除数相同
商 = abs(a)/abs(b)*sign(a)*sign(b)余数 = a-b*商 = abs(a)%abs(b)*sign(a)
- 求模操作 (a mod b):
- 模的符号与除数相同
商 = abs(a)/abs(b)-(sign(a)*sign(b)==1?0:abs(b))模 = a-b*商 = abs(abs(a)%abs(b)-(sign(a)*sign(b)==1?0:abs(b))*sign(b)
其中sign(a)为取a的正负符号,正为1,负为-1,0为0
实际对比
对于正数,两者结果相同:
对于负数,结果可能不同:
1 |
|
1 | # 求模 |
表格对比
| 表达式 | 求余 (C/Java) | 求模 (Python) |
|---|---|---|
| 5 % 3 | 2 | 2 |
| -5 % 3 | -2 | 1 |
| -5 % -3 | -2 | -2 |
| 5 % -3 | 2 | -1 |
转换公式
默认求模的程序语言:Python, Ruby
默认求余的程序语言:C, C++, Java, JavaScript
如果想在求余的语言中实现求模:1
2
3
4int mod(int a, int b) {
int r = a % b;
return r < 0 ? r + abs(b) : r;
}
如果想在求模的语言中实现求余:1
2
3
4
5def remainder(a, b):
r = a % b
if (a < 0 and b > 0) or (a > 0 and b < 0):
return r - b
return r
模意义下的加减乘除
$
(a+b)\bmod c=((a\bmod c)+(b\bmod c))\bmod c\\
(a-b)\bmod c=((a\bmod c)-(b\bmod c))\bmod c\\
(a\times b)\bmod c=((a\bmod c)\times (b\bmod c))\bmod c
$
但是注意,除法就不是这样的了
$
(a\div b)\bmod c=(a\times b^{-1})\bmod c=((a\bmod c)\times (b^{-1}\bmod c))\bmod c
$
$b^{-1}$是逆元