跳转至

模运算

假设 \(a\) 是被除数(dividend),\(n\) 是除数(divisor),\(q\) 是商(quotient),\(r\) 是余数(remainder),模运算

\[ r = a \bmod n \]

最基本的要求是

\[ \left\{\begin{array}{l} q \in \mathbb{Z} \\ a=nq+r \\ |r|<|n| \end{array}\right. \]

\(n=0\) 时,模运算的结果通常是未定义的。

余数的符号

尽管有上面的要求,\(r\) 的符号仍然有歧义。余数 \(r\) 的符号与计算商 \(q\) 时使用的取整函数有关。参考:Modulo - Wikipedia

取整方式 余数
truncate,向零取整,只取整数部分 \(q = \mathrm{truncate} \left(\dfrac{a}{n} \right)\) 符号与被除数 \(a\) 一致
floor,向下取整 \(q=\left\lfloor \dfrac{a}{n} \right\rfloor\) 符号与除数 \(n\) 一致
ceil,向上取整 \(q=\left\lceil \dfrac{a}{n} \right\rceil\) 符号与除数 \(n\) 相反
round银行家舍入 \(q=\mathrm{round} \left(\dfrac{a}{n} \right)\) IEEE Remainder,范围 \(\left[ -\dfrac{n}{2},\dfrac{n}{2} \right]\)
欧几里得除法 \(q=\mathrm{sgn}(n) \left\lfloor \dfrac{a}{\|n\|} \right\rfloor\) 非负

当被除数和除数都是正数时,truncatefloor欧几里得除法 方式的结果一样。

不同实现

在 C / C++ / C# / Go / Java 等语言中,% 运算符使用 truncate 方式,在 Python / Lua 5 等语言中 % 使用 floor 方式。

在数学中常用 欧几里得除法 方式

\[ a \bmod n = a - |n| \left\lfloor \dfrac{a}{|n|} \right\rfloor \]

因为它具有良好的数学性质。

性质 1

\[ (a \pm b) \bmod p = ((a \bmod p) \pm (b \bmod p)) \bmod p \]

性质 2

\[ ab \bmod p = ((a \bmod p)(b \bmod p)) \bmod p \]

性质 3

\[ a^b \bmod p = (a \bmod p)^b \bmod p \]

相关文章