取模和取余

通常情况下,取模运算(MOD)和取余运算(REM)被混为一谈,因为在大多数的编程语言里,都用 ” % ” 符号来表示取模运算或者取余运算。所以有必要编写本文档,来为在此环节遇到问题的程序员理清思路,同时也提醒各位需要注意在不同编程语言环境下 ” % ” 运算符的具体意义,因为在有负数存在的情况下,两者的结果是不一样的。


首先,我们需要区分两者的概念。

取模(MOD):

给定一个正整数p,任意一个整数n,一定存在等式 :
n = k * p + r ;
其中 k、r 是整数,且 0 ≤ r < p,则称 k 为 n 除以 p 的商,r 为 n 除以 p 的余数。
对于正整数 p 和整数 a, b,定义如下运算:
取模运算:a % p(或a mod p),其结果表示a除以p的余数。
模p加法: 其结果是a + b算术和除以p的余数。
模p减法: 其结果是a - b算术差除以p的余数。
模p乘法: 其结果是 a * b算术乘法除以p的余数。

取余(REM):

给定一个正整数p,任意一个整数n,一定存在等式 :
n = k * p + r ;
其中 k、r 是整数,且 0 ≤ r < p,则称 k 为 n 除以 p 的商,r 为 n 除以 p 的余数。
取余运算:是指希望一个较小的数除以另一个较大的数,从而获得的不够除的部分就是余数,就是取余运算的结果。


接下来,需要说明的是,取模运算(“Modulo Operation”)和取余运算(“Remainder Operation”)两者概念虽有重叠的部分但又不完全一致。主要的区别在于对负整数进行除法运算时操作不同。取模运算主要是用于计算机术语中。取余运算则更多是数学概念。模运算在数论和程序设计中都有着广泛的应用。


对于整型数a,b来说,取模运算或者取余运算的方法都是:

1.求整数商: c = a / b;
2.计算模或者余数: r = a - c * b.

取模运算和取余运算在第一步不同: 取余运算在取c的值时,向0 方向舍入(fix()函数); 取模运算在计算c的值时,向无穷小方向舍入(floor()函数)。
因此,当a和b符号一致时,取模运算和取余运算所得的c的值一致,因此结果一致。但是当符号不一致的时候,结果不一样。


具体来说,取模运算结果的符号和b一致,取余运算结果的符号和a一致。
在C语言中,%符号表示的是取余运算,在python脚本中,%表示的是取模。
(通常取模运算中b不允许是负数,但是在python 2.5.1里可以在%后面跟负数,因为python语言中除法的结果是向0舍入,因此计算结果是取模!)


Example:

例如:计算-7 Mod 4
那么:a = -7;b = 4;
第一步:求整数商c,如进行取模运算c = -2(向负无穷方向舍入),取余c = -1(向0方向舍入);
第二步:计算模和余数的公式相同( r = a - c * b ),但因c的取值不同,取模时r = 1,取余时r = -3。


倘若读者已经了解并掌握了两者的区别,也就能很好的理解:“当我们赋值给一个无符号类型,一个超出它表示范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数。”这句话。

例如, 8比特大小的unsigned char 可以表示0 至 255 区间内的值, 如果我么赋值给此类型变量一个区间以外的值,则实际的结果是该值对256取模后所得的余数。 因此, 把 -1 赋值为8比特大小的unsigned char 所得的结果是255.