跳转到内容

模除

维基百科,自由的百科全书
  商数 () 和   余数 () 作为被除数 () 的函数时的图像。左侧是除数为正的情况,右侧除数为负。从上至下分别使用了:向零取整、向下取整和欧几里得除法

模除(英语:modulo 有时也称作 modulus),又称模数取模取模运算等,它得出一个数除以另一个数的余数。给定两个正数:被除数除数(通常缩写为),得到的是使用欧几里得除法时的余数所得之数被称为小数部分。

举个例子:计算表达式得到,因为的商为而余数为;而得到,因为的商为而余数为;做除法不能整除时得到是有理数,平常使用的计算器采用了有限数位十进制表示法,它以小数点分隔整数部分和小数部分,比如

虽然通常情况下模除的被除数和除数都是整数,但许多计算系统允许其他类型的数值运算,比如对浮点数取模。在所有计算系统中当被除数和除数都是正数时,结果的余数的范围为;而经常是未定义的,在编程语言里可能会导致除以零错误。当被除数或除数为负数时,不同的编程语言对结果有不同的处理。

各种定义

在数学中,取模运算的结果就是欧几里德除法余数。当然也有许多其他的定义方式。计算机和计算器有许多种表示和储存数字的方法,因此在不同的硬件环境下、不同的编程语言中,取模运算有着不同的定义。

几乎所有的计算系统中,除以得到商和余数均满足以下式子:

1

即使如此,当余数时,余数的符号仍然是有歧义的:余数非时,它的符号有两种选择,一个是正号而另一个是负号[a]。通常情况下,在数论中总是选择正余数。但在编程中,选择余数的符号依赖于编程语言和被除数或除数的符号。在编程语言所定义的整数模除中,ISO/IEC标准Pascal[1]ALGOL 68[2],在计算出的余数r为负数时,返回正数作为结果[b];另一些编程语言如ISO/IEC C90,当被除数或除数是负数时,C90标准并没有做具体的规定,而是留给编译器去定义并实现[3]。在大多数系统中是未定义的,虽然有些系统定义它就等于。更多详情参见后续章节表格。

  • 很多取模的实现都使用了“截断除法”(英语:truncated division),商经由截尾函数来定义,商向零取整,结果等于普通除法所得的小数靠近方向的第一个整数:

    余数和被除数符号一致:

  • 高德纳定义的“下取整除法”(英语:floored division[4],商经由下取整函数来定义,商总是向负无穷取整,即使商已经是负数:

    余数和除数符号一致:

  • Raymond T. Boute使用的欧几里得除法定义中[5],要求满足,在这种情况下:

    这里的符号函数,余数总是非负数:

  • Common Lisp的round函数和IEEE 754英语IEEE 754-1985使用“修约除法”(英语:rounded division),商经由修约函数约半成偶)来定义为:

    当商为偶数时,余数范围是;当商为奇数时,余数范围是

  • Common Lisp的ceiling函数使用“上取整除法”(英语:ceiling division),商经由上取整函数定义为:

    余数与除数有相反的符号:

记号

一些计算器有取模mod()按钮,很多编程语言里也有类似的函数,通常像mod(a, n)这样。有些语言也支持在表达式内使用%modMod作为取模或取余操作符,比如a % na mod n

在一些没有mod()函数的环境中或许可使用等价的:a - (n * int(a/n))。这里的int()函数事实上等价于截断函数。

性质及恒等式

一些取模操作,经过分解和展开可以等同于其他数学运算。这在密码学的证明中十分有用,例如:迪菲-赫尔曼密钥交换

  • 恒等式:
    • 对所有的正数 有:
    • 如果 是一个质数,且不为 因数,此时由费马小定理有:
  • 逆运算:
    • .
    • 表示模反元素。当且仅当 互质时,等式左侧有定义:
  • 分配律:
  • 除法定义:仅当式子右侧有定义时,即 互质时有:,其他情况为未定义的。
  • 乘法逆元:.

编程语言实现

在各种编程语言中的模除运算
语言 算符 整数 浮点数 定义
ABAP MOD 欧几里得式
ActionScript % 截断
Ada mod 下取整[6]
rem 截断[6]
ALGOL 68 ÷×, mod 类似欧几里得式[c]
AMPL mod 截断
APL |[d] 下取整
AppleScript mod 截断
AutoLISP (rem d n) 截断
AWK % 截断
bash % 截断
BASIC Mod 实现各异
bc % 截断
C
C++
%, div 截断[e]
fmod (C)
std::fmod (C++)
截断[9]
remainder (C)
std::remainder (C++)
修约
C# % 截断
Math.IEEERemainder 修约[10]
Clarion英语Clarion (programming language) % 截断
Clean rem 截断
Clojure mod 下取整[11]
rem 截断[12]
COBOL FUNCTION MOD 下取整[13]
FUNCTION REM 截断[13]
CoffeeScript % 截断
%% 下取整[14]
ColdFusion %, MOD 截断
Common Intermediate Language rem (有符号) 截断[15]
rem.un (无符号) 不适用
Common Lisp mod 下取整
rem 截断
Crystal英语Crystal (programming language) %, modulo 下取整
remainder 截断
D % 截断[16]
Dart % 欧几里得式[17]
remainder() 截断[18]
Eiffel \\ 截断
Elixir rem/2 截断[19]
Integer.mod/2 下取整[20]
Elm modBy 下取整[21]
remainderBy 截断[22]
Erlang rem 截断
math:fmod/2 截断 (同于C)[23]
Euphoria mod 下取整
remainder 截断
F# % 截断
Math.IEEERemainder 修约[10]
Factor mod 截断
FileMaker Mod 下取整
Forth mod 实现定义
fm/mod 下取整
sm/rem 截断
Fortran mod 截断
modulo 下取整
Frink英语Frink (programming language) mod 下取整
Full BASIC英语Full BASIC MOD 下取整[24]
REMAINDER 截断[25]
GLSL % 未定义[26]
mod 下取整[27]
GameMaker Studio (GML) mod, % 截断
GDScript (Godot) % 截断
fmod 截断
posmod 欧几里得式
fposmod 欧几里得式
Go % 截断[28]
math.Mod 截断[29]
big.Int.Mod 欧几里得式[30]
big.Int.Rem 截断[31]
Groovy % 截断
Haskell mod 下取整[32]
rem 截断[32]
Data.Fixed.mod' (GHC) 下取整
Haxe % 截断
HLSL % 未定义[33]
J |[d] 下取整
Java % 截断
Math.floorMod 下取整
JavaScript
TypeScript
% 截断
Julia mod 下取整[34]
%, rem 截断[35]
Kotlin %, rem 截断[36]
mod 下取整[37]
ksh % 截断 (同于POSIX sh)
fmod 截断
LabVIEW mod 截断
LibreOffice =MOD() 下取整
Logo MODULO 下取整
REMAINDER 截断
Lua 5 % 下取整
Lua 4 mod(x,y) 截断
Liberty BASIC英语Liberty BASIC MOD 截断
Mathcad mod(x,y) 下取整
Maple e mod m (默认), modp(e, m) 欧几里得式
mods(e, m) 修约
frem(e, m) 修约
Mathematica Mod[a, b] 下取整
MATLAB mod 下取整
rem 截断
Maxima mod 下取整
remainder 截断
Maya Embedded Language英语Maya Embedded Language % 截断
Microsoft Excel =MOD() 下取整
Minitab MOD 下取整
Modula-2 MOD 下取整
REM 截断
MUMPS英语MUMPS # 下取整
Netwide Assembler (NASM, NASMX) %, div (无符号) 不适用
%% (有符号) 实现定义[38]
Nim mod 截断
Oberon MOD 类似下取整[f]
Objective-C % 截断 (同于C99)
Object Pascal, Delphi mod 截断
OCaml mod 截断[39]
mod_float 截断[40]
Occam \ 截断
Pascal (ISO-7185和ISO-10206) mod 类似欧几里得式[c]
Perl % 下取整[g]
POSIX::fmod 截断
PHP % 截断[42]
fmod 截断[43]
PIC BASIC Pro \\ 截断
PL/I mod 下取整 (ANSI PL/I)
PowerShell % 截断
Programming Code (PRC英语PRC (Palm OS)) MATH.OP - 'MOD; (\)' 未定义
Progress英语OpenEdge Advanced Business Language modulo 截断
Prolog (ISO 1995[44]) mod 下取整
rem 截断
PureBasic %, Mod(x,y) 截断
PureScript `mod` 欧几里得式[45]
Pure Data % 截断 (同于C)
mod 下取整
Python % 下取整
math.fmod 截断
math.remainder 修约
Q# % 截断[46]
R %% 下取整[47]
Racket modulo 下取整
remainder 截断
Raku % 下取整
RealBasic英语RealBasic MOD 截断
Reason mod 截断
Rexx // 截断
RPG英语IBM RPG %REM 截断
Ruby %, modulo() 下取整
remainder() 截断
Rust % 截断
rem_euclid() 欧几里得式[48]
SAS MOD 截断
Scala % 截断
Scheme modulo 下取整
remainder 截断
Scheme R6RS mod 欧几里得式[49]
mod0 修约[49]
flmod 欧几里得式
flmod0 修约
Scratch mod 下取整
Seed7英语Seed7 mod 下取整
rem 截断
SenseTalk英语SenseTalk modulo 下取整
rem 截断
Unix shell (包括bash、ash等。) % 截断 (同于C)[50]
Smalltalk \\ 下取整
rem: 截断
Snap! mod 下取整
Spin英语Parallax Propeller#Built in Spin byte code interpreter // 下取整
Solidity % 下取整
SQL (SQL:1999英语SQL:1999) mod(x,y) 截断
SQL (SQL:2011英语SQL:2011) % 截断
Standard ML mod 下取整
Int.rem 截断
Real.rem 截断
Stata mod(x,y) 欧几里得式
Swift % 截断[51]
remainder(dividingBy:) 修约[52]
truncatingRemainder(dividingBy:) 截断[53]
Tcl % 下取整
fmod() 截断 (同于C)
tcsh % 截断
Torque英语Torque (game engine) % 截断
Turing英语Turing (programming language) mod 下取整
Verilog (2001) % 截断
VHDL mod 下取整
rem 截断
VimL % 截断
Visual Basic Mod 截断
WebAssembly i32.rem_u, i64.rem_u (无符号) 不适用
i32.rem_s, i64.rem_s (有符号) 截断[54]
x86 assembly英语x86 assembly language DIV(无符号) 不适用
IDIV(有符号) 截断
XBase++英语XBase++ % 截断
Mod() 下取整
Zig %, @mod, @rem 截断[55]
Z3 theorem prover英语Z3 Theorem Prover div, mod 欧几里得式

此外,很多计算机系统提供divmod功能,它同时产生商和余数。例子x86架构IDIV指令,C编程语言的div()函数,和Pythondivmod()函数。

常见错误

当取模的结果与被除数符号相同时,可能会导致意想不到的错误。

举个例子:如果需要判断一个整数是否为奇数,有人可能会测试这个数除 2 的余数是否为 1:

bool is_odd(int n) {
    return n % 2 == 1;
}

但在一个取模结果与被除数符号相同的编程语言里,这样做是错的。因为当被除数 n 是奇数且为负数时, 得到 −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)

例子,假定 x 为正数:

x % 2 == x & 1
x % 4 == x & 3
x % 8 == x & 7

在进行位操作比取模操作效率更高的设备或软件环境中,以上形式的取模运算速度更快。[56]

编译器可以自动识别出对 2 的 n 次幂取模的表达式,自动将其优化为 expression & (constant-1)。这样可以在兼顾效率的情况下写出更整洁的代码。这个优化在取模结果与被除数符号一致的语言中(包括 C 语言)不能使用,除非被除数是无符号整数。这是因为如果被除数是负数,则结果也是负数,但 expression & (constant-1) 总是正数,进行这样的优化就会导致错误,无符号整数则没有这个问题。

用途

  • 取模运算可用于判断一个数是否能被另一个数整除。对 2 取模即可判断整数的奇偶性;从 2 到 取模则可判断一个数是否为质数。
  • 进制之间的转换。
  • 用于求取最大公约数的辗转相除法使用取模运算。
  • 密码学中的应用:从古老的凯撒密码到现代常用的RSA椭圆曲线密码,它们的实现过程均使用了取模运算。

参见

脚注

  1. ^ 从数学上讲,正和负只是满足不等式的无穷多个解中的两个。
  2. ^ ISO Pascal要求模除运算的除数n为正数。
  3. ^ 3.0 3.1 按Boute的研讨,ISO Pascal和Algol68的divmod定义不能维持除法恒等式D = d · (D / d) + D % d
  4. ^ 4.0 4.1 α|ω计算,得出ω除以α的余数。
  5. ^ C99C++11%的行为定义为截断。[7]此前的标准将其行为留给实现定义。[8]
  6. ^ 除数必须是整数,否则未定义。
  7. ^ Perl通常使用机器无关的算术模除运算。其例子和异常,参见关于乘法运算的Perl文档。[41]

参考文献

  1. ^ ISO/IEC 7185, Information Technology—Programming Languages–Pascal. International Standard, 2nd ed. (PDF). ISO/IEC 7185, 1990 (E). 
    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.
    Kathleen Jensen, Niklaus Wirth. PASCAL User Manual and Report - ISO Pascal Standard (PDF). 1991. 
    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

  2. ^ A. van Wijngaarden, B. J. Mailloux, J. E. L. Peck, C. H. A. Koster, M. Sintzoff, C. H. Lindsey, L. G. L.T. Meertens and R. G. Fisker. Revised Report on the Algorithmic Language Algol 68. IFIP W.G. 2.1. 
    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);
    
  3. ^ Jones, Derek M. The New C Standard: An Economic and Cultural Commentary (PDF). Addison-Wesley. 2003 [2018-07-11]. ISBN 9780201709179. (原始内容 (PDF)存档于2018-07-11) (英语). 
    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. ^ Knuth, Donald. E. The Art of Computer Programming. Addison-Wesley. 1972 (英语). 
    If is any real number, we write
    = the greatest integer less than or equal to (the floor of );
    = the least integer greater than or equal to (the ceiling of ).
    ……
    The following formulas and examples are easily verified:
    ……
    if and only if is an integer,
    if and only if is not an integer;
    ;   .

    ……
    If and are any real numbers, we define the following binary operation:

    ;  .  (1)

    From this definition we can see that, when ,

    .  (2)

    Consequently
    a) if , then ;
    b) if , then ;
    c) the quantity is an integral multiple of .
    We call the remainder when is divided by ; similarly, we call the quotient.
    When and are integers, “” is therefore a familiar operation:

    ,  ,  .  (3)

    We have if and only if is a multiple of , that is, if and only if is divisible by . The notation , read “ divides ,” means that is a positive integer and .
    The “” operation is useful also when and take arbitrary real values. For example, with trigonometric functions we can write

    .

    The quantity is the fractional part of ; we have, by Eq. (1),

    .
  5. ^ Boute, Raymond T. The Euclidean definition of the functions div and mod. ACM Transactions on Programming Languages and Systems (ACM Press (New York, NY, USA)). April 1992, 14 (2): 127–144. doi:10.1145/128861.128862 (英语). 
    Let us recall Euclid’s theorem.
    THEOREM. For any real numbers and with , there exists a unique pair of numbers satisfying the following conditions:
    (a) ;
    (b) ;
    (c) .
    For the particular case of integers, the conditions (a)-(c) correspond to part of the axioms for Euclidean rings [9].
    With the notational conventions of the theorem, we define and . Clearly the correspondingly labeled conditions are satisfied.
    Properties

    where and is as defined earlier. ()
  6. ^ 6.0 6.1 ISO/IEC 8652:2012 - Information technology — Programming languages — Ada. ISO, IEC. 2012. sec. 4.5.5 Multiplying Operators. 
  7. ^ C99 specification (ISO/IEC 9899:TC2) (PDF). sec. 6.5.5 Multiplicative operators. 2005-05-06 [16 August 2018]. 
  8. ^ ISO/IEC 14882:2003: Programming languages – C++. International Organization for Standardization (ISO), International Electrotechnical Commission (IEC). 2003. sec. 5.6.4. the binary % operator yields the remainder from the division of the first expression by the second. .... If both operands are nonnegative then the remainder is nonnegative; if not, the sign of the remainder is implementation-defined 
  9. ^ ISO/IEC 9899:1990: Programming languages – C. ISO, IEC. 1990. sec. 7.5.6.4. The fmod function returns the value x - i * y, for some integer i such that, if y is nonzero, the result has the same sign as x and magnitude less than the magnitude of y. 
  10. ^ 10.0 10.1 dotnet-bot. Math.IEEERemainder(Double, Double) Method (System). Microsoft Learn. [2022-10-04] (美国英语). 
  11. ^ clojure.core - Clojure v1.10.3 API documentation. clojure.github.io. [2022-03-16]. 
  12. ^ clojure.core - Clojure v1.10.3 API documentation. clojure.github.io. [2022-03-16]. 
  13. ^ 13.0 13.1 ISO/IEC JTC 1/SC 22/WG 4. ISO/IEC 1989:2023 – Programming language COBOL需要付费订阅. ISO. January 2023. 
  14. ^ CoffeeScript operators
  15. ^ ISO/IEC JTC 1/SC 22. ISO/IEC 23271:2012 — Information technology — Common Language Infrastructure (CLI). ISO. February 2012. §§ III.3.55–56. 
  16. ^ Expressions - D Programming Language. dlang.org. [2021-06-01]. 
  17. ^ operator % method - num class - dart:core library - Dart API. api.dart.dev. [2021-06-01]. 
  18. ^ remainder method - num class - dart:core library - Dart API. api.dart.dev. [2021-06-01]. 
  19. ^ Kernel — Elixir v1.11.3. hexdocs.pm. [2021-01-28]. 
  20. ^ Integer — Elixir v1.11.3. hexdocs.pm. [2021-01-28]. 
  21. ^ Basics - core 1.0.5. package.elm-lang.org. [2022-03-16]. 
  22. ^ Basics - core 1.0.5. package.elm-lang.org. [2022-03-16]. 
  23. ^ Erlang -- math. erlang.org. [2021-06-01]. 
  24. ^ ANSI. Programming Languages — Full BASIC. New York: American National Standards Institute. 28 January 1987. § 5.4.4. X modulo Y, i.e., X-Y*INT(X/Y). 
  25. ^ ANSI. Programming Languages — Full BASIC. New York: American National Standards Institute. 28 January 1987. § 5.4.4. The remainder function, i.e., X-Y*IP(X/Y). 
  26. ^ GLSL Language Specification, Version 4.50.7 (PDF). section 5.9 Expressions. If both operands are non-negative, then the remainder is non-negative. Results are undefined if one or both operands are negative. 
  27. ^ GLSL Language Specification, Version 4.50.7 (PDF). section 8.3 Common Functions. 
  28. ^ The Go Programming Language Specification - The Go Programming Language. go.dev. [2022-02-28]. 
  29. ^ math package - math - pkg.go.dev. pkg.go.dev. [2022-02-28]. 
  30. ^ big package - math/big - pkg.go.dev. pkg.go.dev. [2022-02-28]. 
  31. ^ big package - math/big - pkg.go.dev. pkg.go.dev. [2024-04-12]. 
  32. ^ 32.0 32.1 6 Predefined Types and Classes. www.haskell.org. [2022-05-22]. 
  33. ^ Operators. Microsoft. [2021-07-19]. The % operator is defined only in cases where either both sides are positive or both sides are negative. Unlike C, it also operates on floating-point data types, as well as integers. 
  34. ^ Mathematics · The Julia Language. docs.julialang.org. [2021-11-20]. 
  35. ^ Mathematics · The Julia Language. docs.julialang.org. [2021-11-20]. 
  36. ^ rem - Kotlin Programming Language. Kotlin. [2021-05-05] (英语). 
  37. ^ mod - Kotlin Programming Language. Kotlin. [2021-05-05] (英语). 
  38. ^ Chapter 3: The NASM Language. NASM - The Netwide Assembler version 2.15.05. 
  39. ^ OCaml library : Stdlib. ocaml.org. [2022-02-19]. 
  40. ^ OCaml library : Stdlib. ocaml.org. [2022-02-19]. 
  41. ^ Perl documentation
  42. ^ PHP: Arithmetic Operators - Manual. www.php.net. [2021-11-20]. 
  43. ^ PHP: fmod - Manual. www.php.net. [2021-11-20]. 
  44. ^ ISO 1995
  45. ^ EuclideanRing. 
  46. ^ QuantumWriter. Expressions. docs.microsoft.com. [2018-07-11] (美国英语). 
  47. ^ R: Arithmetic Operators. search.r-project.org. [2022-12-24]. 
  48. ^ F32 - Rust. 
  49. ^ 49.0 49.1 r6rs.org
  50. ^ Shell Command Language. pubs.opengroup.org. [2021-02-05]. 
  51. ^ Apple Developer Documentation. developer.apple.com. [2021-11-20]. 
  52. ^ Apple Developer Documentation. developer.apple.com. [2021-11-20]. 
  53. ^ Apple Developer Documentation. developer.apple.com. [2021-11-20]. 
  54. ^ Rossberg, Andreas (编). WebAssembly Core Specification: Version 2.0. World Wide Web Consortium. § 4.3.2 Integer Operations. 19 April 2022. 
  55. ^ Zig Documentation. Zig Programming Language. [2022-12-18]. 
  56. ^ Horvath, Adam. Faster division and modulo operation - the power of two. July 5, 2012. (原始内容存档于2018-03-05) (英语).