Template:About
Template:Colorbox 商數 (q ) 和 Template:Colorbox 餘數 (r ) 作為被除數 (a ) 的函數時的圖像。左侧是除数 为正的情况,右侧除数 为负。从上至下分别使用了:向零取整、向下取整和欧几里得除法 。
模除 (Template:Lang-en 有时也称作 modulus),又稱模数 、取模 、取模運算 等,它得出一个数除以另一个数的余数。给定两个正数:被除数 a 和除数 n ,a modulo n (通常缩写为a mod n ),得到的是使用欧几里得除法 时的余数 。a mod 1 所得之数被称为a 的小数 部份。
举个例子:计算表达式5 mod 2 得到1 ,因为5 ÷ 2 的商为2 而余数为1 ;而9 mod 3 得到0 ,因为9 ÷ 3 的商为3 而余数为0 ;做除法不能整除 时得到是有理数 ,平常使用的计算器采用了有限 个数位 的十进制 表示法,它以小数点 分隔整数 部份和小数 部份,比如5 ÷ 2 = 2 . 5 。
虽然通常情况下模除的被除数a 和除数n 都是整数,但许多计算系统允许其他类型的数值运算,比如对浮点数 取模。在所有计算系统中当被除数a 和除数n 都是正数时,结果的余数r 的范围为0 ≤ r < n ;而a mod 0 经常是未定义的,在编程语言里可能会导致除以零 错误。当被除数a 或除数n 为负数时,不同的编程语言对结果有不同的处理。
各种定义
在数学中,取模运算的结果就是欧几里德除法 的余数 。当然也有许多其他的定义方式。计算机和计算器有许多种表示和储存数字的方法,因此在不同的硬件环境下、不同的编程语言中,取模运算有着不同的定义。
几乎所有的计算系统中,a 除以n 得到商q 和余数r 均满足以下式子:
Template:NumBlk
即使如此,当余数 非0 时,余数的符号仍然是有歧义的:余数非0 时,它的符号有两种选择,一个是正号而另一个是负号Template:Efn 。通常情况下,在数论中总是选择正余数。但在编程中,选择余数的符号依赖于编程语言和被除数a 或除数n 的符号。在编程语言所定义的整数 模除中,ISO/IEC标准Pascal [ 1] 和ALGOL 68 [ 2] ,在计算出的余数r为负数时,返回正数r + | n | 作为结果Template:Efn ;另一些编程语言如ISO/IEC C90 ,当被除数a 或除数n 是负数时,C90标准并没有做具体的规定,而是留给编译器去定义并实现[ 3] 。在大多数系统中a mod 0 是未定义的,虽然有些系统定义它就等于a 。更多详情参见后续章节表格。
Template:Bulleted list
记号
一些计算器有取模Template:Math 按钮,很多编程语言里也有类似的函数,通常像mod(a, n)这样。有些语言也支持在表达式内使用%、mod或Mod作为取模或取余操作符,比如a % n或a mod n。
在一些没有Template:Math 函数的环境中或许可使用等价的:a - (n * int(a/n))。这里的int()函数事实上等价于截断函数。
性质及恒等式
一些取模操作,经过分解和展开可以等同于其他数学运算。这在密码学 的证明中十分有用,例如:迪菲-赫爾曼密鑰交換 。
恒等式:
( a mod n ) mod n = a mod n
对所有的正数 x 有:n x mod n = 0
如果 p 是一个质数 ,且不为 b 的因数 ,此时由费马小定理 有:a b p − 1 mod p = a mod p
逆运算:
[ ( − a mod n ) + ( a mod n ) ] mod n = 0 .
b − 1 mod n 表示模反元素 。当且仅当 b 与 n 互质时,等式左侧有定义:[ ( b − 1 mod n ) ( b mod n ) ] mod n = 1 。
分配律:
( a + b ) mod n = [ ( a mod n ) + ( b mod n ) ] mod n
a b mod n = [ ( a mod n ) ( b mod n ) ] mod n
除法定义:仅当式子右侧有定义时,即 b 、n 互质时有:a b mod n = [ ( a mod n ) ( b − 1 mod n ) ] mod n ,其他情况为未定义的。
乘法逆元:[ ( a b mod n ) ( b − 1 mod n ) ] mod n = a mod n .
编程语言实现
在各种编程语言中的模除运算
语言
算符
整数
浮点数
定义
ABAP
Template:Code
Template:Yes
Template:Yes
欧几里得式
ActionScript
Template:Code
Template:Yes
Template:No
截断
Ada
Template:Code
Template:Yes
Template:No
下取整[ 4]
Template:Code
Template:Yes
Template:No
截断[ 4]
ALGOL 68
Template:Code , Template:Code
Template:Yes
Template:No
类似欧几里得式Template:Efn
AMPL
Template:Code
Template:Yes
Template:No
截断
APL
|Template:Efn
Template:Yes
Template:Yes
下取整
AppleScript
Template:Code
Template:Yes
Template:No
截断
AutoLISP
Template:Code
Template:Yes
Template:No
截断
AWK
Template:Code
Template:Yes
Template:No
截断
bash
Template:Code
Template:Yes
Template:No
截断
BASIC
Template:Code
Template:Yes
Template:No
实现各异
bc
Template:Code
Template:Yes
Template:No
截断
C Template:Break C++
Template:Code , Template:Code
Template:Yes
Template:No
截断Template:Efn
Template:Code (C)Template:Break Template:Code (C++)
Template:No
Template:Yes
截断[ 5]
Template:Code (C)Template:Break Template:Code (C++)
Template:No
Template:Yes
修约
C#
Template:Code
Template:Yes
Template:Yes
截断
Template:Code
Template:No
Template:Yes
修约[ 6]
Template:En-link
Template:Code
Template:Yes
Template:No
截断
Clean
Template:Code
Template:Yes
Template:No
截断
Clojure
Template:Code
Template:Yes
Template:No
下取整[ 7]
Template:Code
Template:Yes
Template:No
截断[ 8]
COBOL
Template:Code
Template:Yes
Template:No
下取整[ 9]
Template:Code
Template:Yes
Template:Yes
截断[ 9]
CoffeeScript
Template:Code
Template:Yes
Template:No
截断
Template:Code
Template:Yes
Template:No
下取整[ 10]
ColdFusion
Template:Code , Template:Code
Template:Yes
Template:No
截断
Common Intermediate Language
Template:Code (有符号)
Template:Yes
Template:Yes
截断[ 11]
Template:Code (无符号)
Template:Yes
Template:No
Template:N/A
Common Lisp
Template:Code
Template:Yes
Template:Yes
下取整
Template:Code
Template:Yes
Template:Yes
截断
Template:En-link
Template:Code , Template:Code
Template:Yes
Template:Yes
下取整
Template:Code
Template:Yes
Template:Yes
截断
D
Template:Code
Template:Yes
Template:Yes
截断[ 12]
Dart
Template:Code
Template:Yes
Template:Yes
欧几里得式[ 13]
Template:Code
Template:Yes
Template:Yes
截断[ 14]
Eiffel
Template:Code
Template:Yes
Template:No
截断
Elixir
Template:Code
Template:Yes
Template:No
截断[ 15]
Template:Code
Template:Yes
Template:No
下取整[ 16]
Elm
Template:Code
Template:Yes
Template:No
下取整[ 17]
Template:Code
Template:Yes
Template:No
截断[ 18]
Erlang
Template:Code
Template:Yes
Template:No
截断
Template:Code
Template:No
Template:Yes
截断 (同于C)[ 19]
Euphoria
Template:Code
Template:Yes
Template:No
下取整
Template:Code
Template:Yes
Template:No
截断
F#
Template:Code
Template:Yes
Template:Yes
截断
Template:Code
Template:No
Template:Yes
修约[ 6]
Factor
Template:Code
Template:Yes
Template:No
截断
FileMaker
Template:Code
Template:Yes
Template:No
下取整
Forth
Template:Code
Template:Yes
Template:No
实现定义
Template:Code
Template:Yes
Template:No
下取整
Template:Code
Template:Yes
Template:No
截断
Fortran
Template:Code
Template:Yes
Template:Yes
截断
Template:Code
Template:Yes
Template:Yes
下取整
Template:En-link
Template:Code
Template:Yes
Template:No
下取整
Template:En-link
Template:Code
Template:Yes
Template:Yes
下取整[ 20]
Template:Code
Template:Yes
Template:Yes
截断[ 21]
GLSL
Template:Code
Template:Yes
Template:No
未定义[ 22]
Template:Code
Template:No
Template:Yes
下取整[ 23]
GameMaker Studio (GML)
Template:Code , Template:Code
Template:Yes
Template:No
截断
GDScript (Godot)
Template:Code
Template:Yes
Template:No
截断
Template:Code
Template:No
Template:Yes
截断
Template:Code
Template:Yes
Template:No
欧几里得式
Template:Code
Template:No
Template:Yes
欧几里得式
Go
Template:Code
Template:Yes
Template:No
截断[ 24]
Template:Code
Template:No
Template:Yes
截断[ 25]
Template:Code
Template:Yes
Template:No
欧几里得式[ 26]
Template:Code
Template:Yes
Template:No
截断[ 27]
Groovy
Template:Code
Template:Yes
Template:No
截断
Haskell
Template:Code
Template:Yes
Template:No
下取整[ 28]
Template:Code
Template:Yes
Template:No
截断[ 28]
Template:Code (GHC )
Template:No
Template:Yes
下取整
Haxe
Template:Code
Template:Yes
Template:No
截断
HLSL
Template:Code
Template:Yes
Template:Yes
未定义[ 29]
J
|Template:Efn
Template:Yes
Template:No
下取整
Java
Template:Code
Template:Yes
Template:Yes
截断
Template:Code
Template:Yes
Template:No
下取整
JavaScript Template:Break TypeScript
Template:Code
Template:Yes
Template:Yes
截断
Julia
Template:Code
Template:Yes
Template:Yes
下取整[ 30]
Template:Code , Template:Code
Template:Yes
Template:Yes
截断[ 31]
Kotlin
Template:Code , Template:Code
Template:Yes
Template:Yes
截断[ 32]
Template:Code
Template:Yes
Template:Yes
下取整[ 33]
ksh
Template:Code
Template:Yes
Template:No
截断 (同于POSIX sh)
Template:Code
Template:No
Template:Yes
截断
LabVIEW
Template:Code
Template:Yes
Template:Yes
截断
LibreOffice
Template:Code
Template:Yes
Template:No
下取整
Logo
Template:Code
Template:Yes
Template:No
下取整
Template:Code
Template:Yes
Template:No
截断
Lua 5
Template:Code
Template:Yes
Template:Yes
下取整
Lua 4
Template:Code
Template:Yes
Template:Yes
截断
Template:En-link
Template:Code
Template:Yes
Template:No
截断
Mathcad
Template:Code
Template:Yes
Template:No
下取整
Maple
Template:Code (默认), Template:Code
Template:Yes
Template:No
欧几里得式
Template:Code
Template:Yes
Template:No
修约
Template:Code
Template:Yes
Template:Yes
修约
Mathematica
Template:Code
Template:Yes
Template:No
下取整
MATLAB
Template:Code
Template:Yes
Template:No
下取整
Template:Code
Template:Yes
Template:No
截断
Maxima
Template:Code
Template:Yes
Template:No
下取整
Template:Code
Template:Yes
Template:No
截断
Template:En-link
Template:Code
Template:Yes
Template:No
截断
Microsoft Excel
Template:Code
Template:Yes
Template:Yes
下取整
Minitab
Template:Code
Template:Yes
Template:No
下取整
Modula-2
Template:Code
Template:Yes
Template:No
下取整
Template:Code
Template:Yes
Template:No
截断
Template:En-link
Template:Code
Template:Yes
Template:No
下取整
Netwide Assembler (NASM , NASMX )
Template:Code , Template:Code (无符号)
Template:Yes
Template:No
Template:N/A
Template:Code (有符号)
Template:Yes
Template:No
实现定义[ 34]
Nim
Template:Code
Template:Yes
Template:No
截断
Oberon
Template:Code
Template:Yes
Template:No
类似下取整Template:Efn
Objective-C
Template:Code
Template:Yes
Template:No
截断 (同于C99)
Object Pascal , Delphi
Template:Code
Template:Yes
Template:No
截断
OCaml
Template:Code
Template:Yes
Template:No
截断[ 35]
Template:Code
Template:No
Template:Yes
截断[ 36]
Occam
Template:Code
Template:Yes
Template:No
截断
Pascal (ISO-7185和ISO-10206)
Template:Code
Template:Yes
Template:No
类似欧几里得式Template:Efn
Perl
Template:Code
Template:Yes
Template:No
下取整Template:Efn
Template:Code
Template:No
Template:Yes
截断
PHP
Template:Code
Template:Yes
Template:No
截断[ 37]
Template:Code
Template:No
Template:Yes
截断[ 38]
PIC BASIC Pro
Template:Code
Template:Yes
Template:No
截断
PL/I
Template:Code
Template:Yes
Template:No
下取整 (ANSI PL/I)
PowerShell
Template:Code
Template:Yes
Template:No
截断
Programming Code (Template:En-link )
Template:Code
Template:Yes
Template:No
未定义
Template:En-link
Template:Code
Template:Yes
Template:No
截断
Prolog (ISO 1995[ 39] )
Template:Code
Template:Yes
Template:No
下取整
Template:Code
Template:Yes
Template:No
截断
PureBasic
Template:Code , Template:Code
Template:Yes
Template:No
截断
PureScript
Template:Code
Template:Yes
Template:No
欧几里得式[ 40]
Pure Data
Template:Code
Template:Yes
Template:No
截断 (同于C)
Template:Code
Template:Yes
Template:No
下取整
Python
Template:Code
Template:Yes
Template:Yes
下取整
Template:Code
Template:No
Template:Yes
截断
Template:Code
Template:No
Template:Yes
修约
Q#
Template:Code
Template:Yes
Template:No
截断[ 41]
R
Template:Code
Template:Yes
Template:Yes
下取整[ 42]
Racket
Template:Code
Template:Yes
Template:No
下取整
Template:Code
Template:Yes
Template:No
截断
Raku
Template:Code
Template:No
Template:Yes
下取整
Template:En-link
Template:Code
Template:Yes
Template:No
截断
Reason
Template:Code
Template:Yes
Template:No
截断
Rexx
Template:Code
Template:Yes
Template:Yes
截断
Template:En-link
Template:Code
Template:Yes
Template:No
截断
Ruby
Template:Code , Template:Code
Template:Yes
Template:Yes
下取整
Template:Code
Template:Yes
Template:Yes
截断
Rust
Template:Code
Template:Yes
Template:Yes
截断
Template:Code
Template:Yes
Template:Yes
欧几里得式[ 43]
SAS
Template:Code
Template:Yes
Template:No
截断
Scala
Template:Code
Template:Yes
Template:Yes
截断
Scheme
Template:Code
Template:Yes
Template:No
下取整
Template:Code
Template:Yes
Template:No
截断
Scheme R6 RS
Template:Code
Template:Yes
Template:No
欧几里得式[ 44]
Template:Code
Template:Yes
Template:No
修约[ 44]
Template:Code
Template:No
Template:Yes
欧几里得式
Template:Code
Template:No
Template:Yes
修约
Scratch
Template:Code
Template:Yes
Template:Yes
下取整
Template:En-link
Template:Code
Template:Yes
Template:Yes
下取整
Template:Code
Template:Yes
Template:Yes
截断
Template:En-link
Template:Code
Template:Yes
Template:No
下取整
Template:Code
Template:Yes
Template:No
截断
Unix shell (包括bash 、ash等。)
Template:Code
Template:Yes
Template:No
截断 (同于C)[ 45]
Smalltalk
Template:Code
Template:Yes
Template:No
下取整
Template:Code
Template:Yes
Template:No
截断
Snap!
Template:Code
Template:Yes
Template:No
下取整
Template:En-link
Template:Code
Template:Yes
Template:No
下取整
Solidity
Template:Code
Template:Yes
Template:No
下取整
SQL (Template:En-link )
Template:Code
Template:Yes
Template:No
截断
SQL (Template:En-link )
Template:Code
Template:Yes
Template:No
截断
Standard ML
Template:Code
Template:Yes
Template:No
下取整
Template:Code
Template:Yes
Template:No
截断
Template:Code
Template:No
Template:Yes
截断
Stata
Template:Code
Template:Yes
Template:No
欧几里得式
Swift
Template:Code
Template:Yes
Template:No
截断[ 46]
Template:Code
Template:No
Template:Yes
修约[ 47]
Template:Code
Template:No
Template:Yes
截断[ 48]
Tcl
Template:Code
Template:Yes
Template:No
下取整
Template:Code
Template:No
Template:Yes
截断 (同于C)
tcsh
Template:Code
Template:Yes
Template:No
截断
Template:En-link
Template:Code
Template:Yes
Template:No
截断
Template:En-link
Template:Code
Template:Yes
Template:No
下取整
Verilog (2001)
Template:Code
Template:Yes
Template:No
截断
VHDL
Template:Code
Template:Yes
Template:No
下取整
Template:Code
Template:Yes
Template:No
截断
VimL
Template:Code
Template:Yes
Template:No
截断
Visual Basic
Template:Code
Template:Yes
Template:No
截断
WebAssembly
Template:Code , Template:Code (无符号)
Template:Yes
Template:No
Template:N/A
Template:Code , Template:Code (有符号)
Template:Yes
Template:No
截断[ 49]
Template:En-link
Template:Code (无符号)
Template:Yes
Template:No
Template:N/A
Template:Code (有符号)
Template:Yes
Template:No
截断
Template:En-link
Template:Code
Template:Yes
Template:Yes
截断
Template:Code
Template:Yes
Template:Yes
下取整
Zig
Template:Code , Template:Code , Template:Code
Template:Yes
Template:Yes
截断[ 50]
Template:En-link
Template:Code , Template:Code
Template:Yes
Template:No
欧几里得式
此外,很多计算机系统提供Template:Code 功能,它同时产生商和余数。例子x86架构 的Template:Code 指令,C编程语言的Template:Code 函数,和Python 的Template:Code 函数。
常见错误
当取模的结果与被除数符号相同时,可能会导致意想不到的错误。
举个例子:如果需要判断一个整数是否为奇数,有人可能会测试这个数除 2 的余数是否为 1:
bool is_odd ( int n ) {
return n % 2 == 1 ;
}
但在一个取模结果与被除数符号相同的编程语言里,这样做是错的。因为当被除数 Template:Math 是奇数且为负数时, n mod 2 得到 −1,此时函数返回“假”。
一种正确的实现是测试取模结果是否为 0,因为余数为 0 时没有符号的问题:
bool is_odd ( int n ) {
return n % 2 != 0 ;
}
或者考虑余数的符号,有两种情况:余数可能为 1 或 -1。
bool is_odd ( int n ) {
return n % 2 == 1 || n % 2 == -1 ;
}
性能问题
可以通过依次计算带余数的除法实现取模操作。特殊情况下,如某些硬件上,存在更快的实现。
例如:2 的 n 次幂的模,可以通过逐位 与运算 实现:
x % 2n == x & (2n - 1)
例子,假定 Template:Math 为正数:
x % 2 == x & 1
x % 4 == x & 3
x % 8 == x & 7
在进行位操作比取模操作效率更高的设备或软件环境中,以上形式的取模运算速度更快。[ 51]
编译器可以自动识别出对 2 的 n 次幂取模的表达式,自动将其优化为 expression & (constant-1)。这样可以在兼顾效率的情况下写出更整洁的代码。这个优化在取模结果与被除数符号一致的语言中(包括 C 语言)不能使用,除非被除数是无符号整数。这是因为如果被除数是负数,则结果也是负数,但 expression & (constant-1) 总是正数,进行这样的优化就会导致错误,无符号整数则没有这个问题。
用途
取模运算可用于判断一个数是否能被另一个数整除。对 2 取模即可判断整数的奇偶性;从 2 到 n − 1 取模则可判断一个数是否为质数。
進制 之間的轉換。
用于求取最大公约数的輾轉相除法 使用取模运算。
密码学中的应用:从古老的凯撒密码 到现代常用的RSA 、椭圆曲线密码 ,它们的实现过程均使用了取模运算。
參見
脚注
Template:Reflist
参考文献
Template:Reflist
↑ Template:Cite web
A term of the form i div j shall be an error if j is zero; otherwise, the value of i div j shall be such that
abs(i) - abs(j) < abs((i div j) * j) <= abs(i)
where the value shall be zero if abs(i) < abs(j); otherwise, the sign of the value shall be positive if i and j have the same sign and negative if i and j have different signs.
A term of the form i mod j shall be an error if j is zero or negative; otherwise, the value of i mod j shall be that value of (i - (k * j)) for integral k such that 0 <= i mod j < j.
NOTE 2 — Only for i >= 0 and j > 0 does the relation (i div j) * j + i mod j = i hold.
Template:Cite web
div
divide and truncate (i.e., value is not rounded)
mod
modulus: let Remainder = A - (A div B) * B; if Remainder < 0 then A mod B = Remainder + B
otherwise A mod B = Remainder
↑ Template:Cite web 10.2.3.3. Operations on integral operands
……
m) OP «÷, %, OVER» = (L INT a, b) L INT:
IF b ≠ L 0
THEN L INT q := L 0, r := ABS a;
WHILE (r := r - ABS b) ≥ L 0 DO q := q + L 1 OD;
(a < L 0 AND b > L 0 OR a ≥ L 0 AND b < L 0 | -q | q)
FI;
n) OP «÷×, ÷*, %*, MOD» = (L INT a, b) L INT:
(L INT r = a - a ÷ b × b; r < 0 | r + ABS b | r);
↑ Template:Cite book
C99 reflects almost universal processor behavior (as does the Fortran Standard). This definition truncates toward zero and the expression (-(a/b) == (-a)/b) && (-(a/b) == a/(-b)) is always true. It also means that the absolute value of the result does not depend on the signs of the operands; for example:
+10 / +3 == +3 +10 % +3 == +1 -10 / +3 == -3 -10 % +3 == -1+10 / -3 == -3 +10 % -3 == +1 -10 / -3 == +3 -10 % -3 == -1
C90
When integers are divided and the division is inexact, if both operands are positive the result of the / operator is the largest integer less than the algebraic quotient and the result of the % operator is positive. If either operand is negative, whether the result of the / operator is the largest integer less than or equal to the algebraic quotient or the smallest integer greater than or equal to the algebraic quotient is implementation-defined, as is the sign of the result of the % operator.
If either operand is negative, the behavior may differ between C90 and C99, depending on the implementation-defined behavior of the C90 implementation.
#include <stdio.h>
int main ( void )
{
int x = -1 ,
y = + 3 ;
if (( x % y > 0 ) ||
(( x + y ) % y == x % y ))
printf ( "This is a C90 translator behaving differently than C99 \n " );
}
Quoting from the C9X Revision Proposal, WG14/N613, that proposed this change:
The origin of this practice seems to have been a desire to map C’s division directly to the “natural” behavior of the target instruction set, whatever it may be, without requiring extra code overhead that might be necessary to check for special cases and enforce a particular behavior. However, the argument that Fortran programmers are unpleasantly surprised by this aspect of C and that there would be negligible impact on code efficiency was accepted by WG14, who agreed to require Fortran-like behavior in C99.
↑ 4.0 4.1 Template:Cite book
↑ Template:Cite book
↑ 6.0 6.1 Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ 9.0 9.1 Template:Cite book
↑ CoffeeScript operators
↑ Template:Cite book
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite book
↑ Template:Cite book
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ 28.0 28.1 Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ ISO 1995
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ 44.0 44.1 r6rs.org
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web
↑ Template:Cite web