数据结构+算法=程序
程序+设计模式=软件

0%

Python中的模运算

所谓取模运算,就是计算两个数相除之后的余数,符号是%。如a % b就是计算a除以b的余数。用数学语言来描述,就是如果存在整数n和m,其中0 <= m < b,使得$ a = n * b + m $,那么$ a \% b = a - n * b = m $。

先测试几个例子:

1
2
3
4
print(9%5)         # 4
print(-9%5) # 1
print(9%-5) # -1
print(-9%-5) # -4

可以看到,数值部分虽然相同,但是正负符号的四种不同组合,会产生完全不同的四种结果。那么这里面有什么规律吗?
实际上,虽然结果不一样,不过取模运算完全遵从统一的规则:

其中$\lfloor\frac{a}{b}\rfloor$表示a除以b的结果向下取整。
比如$9\%5$,先计算$\lfloor\frac{9}{5}\rfloor$,向下取整得到1,然后计算$9-1*5$,得到4;

同理$-9\%5$,先计算$\lfloor\frac{-9}{5}\rfloor$,向下取整得到-2,然后计算$-9-(-2*5)$,得到1;
再来看$9\%-5$:

最后是$-9\%-5$:

虽然知道结果是如何计算出来的,不过人脑不比电脑,这样计算未免太复杂,为避免给大脑增加负担,再根据上面的规则,这里我总结了一个简单的记忆方法:

  1. 对于不带负号的,2个数字都是正数的,直接求结果,这个应该来说是比较简单的,而且无论符号是什么,我们都只计算这个值;
  2. 对于有负号的,不管负号在哪个数字,都去除负号,然后计算步骤1的结果;
  3. 接下来根据负号的位置分为3种情况,假设除数是K,去掉负号后取模的结果是M:
    • 2个数都是负数,直接等于-M
    • 被除数是负数,除数是正数,由于是向下舍入,最后相当于会多加上一个K,也就是说模一定是大于0的,结果是K-M
    • 被除数是正数,除数是负数,刚好相反,结果是M-K,注意这里的K是除数的绝对值,是正数

简单归纳:

  1. 不管有没有负数,先按正数求模得到M
  2. 2个数都为负数,结果是-M
  3. 只有1个数为负数,负数在上,记住结果一定是正的,大数-小数(除数-余数),那么就是K-M
  4. 只有1个数为负数,负数在下,记住结果一定是负的,小数-大数(余数-除数),那么就是M-K

注:此规律的前提是除的结果一定是向下取整,如果你用java去套这个规律会发现完全行不通。