Modular congruence: Difference between revisions
DroneBetter (talk | contribs) m Now I should look quite the fool |
DroneBetter (talk | contribs) m clean up and reword somewhat (using {{frac}}, {{choose}} and {{prod}}, of which I learned since writing this page), add Lucas's and Euler's theorems |
||
| Line 1: | Line 1: | ||
{{cleanup}}{{Glossary}} | {{cleanup}}{{Glossary}} | ||
Two numbers <tt>a,b</tt> are '''congruent''' modulo a third number <tt>n</tt> if their values are equal when integer multiples of <tt>n</tt> are added or subtracted from them such that they both lie in the range <tt>0 | Two numbers <tt>a,b</tt> are '''congruent''' modulo a third number <tt>n</tt> if their values are equal when integer multiples of <tt>n</tt> are added or subtracted from them such that they both lie in the range <tt>0 ≤ x < n</tt> (an operation denoted with the <tt>%</tt> symbol).<ref group="n">In taking <tt>x%n</tt>, when either operand is negative, programming languages' implementations differ in convention. Python ensures that the sign of the output matches that of the second input (the 'modulo base'), ie. <tt>0≥ x%n > n</tt> if n is negative, to make <tt>x//n*n+x%n=x</tt> hold, because Python's floordiv operator <tt>//</tt> rounds towards <tt>-∞</tt>, whereas C matches the first, ie. <tt>-4%3=-1</tt>, because its integer division operator, <tt>/</tt>, returns integers but rounds towards <tt>0</tt>, this article will use the Python convention for signed modulo.</ref> A function returning the value of <tt>x</tt> modulo <tt>n</tt> is given in most programming languages with the <tt>%</tt> operator (ie. <tt>x%n</tt>), and according to the C specification (followed by languages like Python), modulo has the same precedence as multiplication and division, and expressions involving multiple of the same precedence adjacent without brackets will be evaluated left-to-right.<ref group="n">Without modulo or floordiv (only multiplication and division), this is equivalent to division being evaluated before multiplication, as is taught in schools.</ref> | ||
Such equalities under the modulo operation are denoted as <tt> | Such equalities under the modulo operation are denoted as <tt>a ≡ b (mod n)</tt>. For instance, <tt>5 ≡ 8 (mod 3)</tt>, because both of them (after multiples of <tt>3</tt> are subtracted) evaluate to <tt>2</tt>. Alternatively (for integer modulo bases <tt>n</tt>), <tt>x%n</tt> is equivalent to taking <tt>x</tt>'s expansion in base <tt>n</tt> and truncating the digits with greater place value than <tt>1</tt>. Modular arithmetic is generally concerned with the behaviour of operations under the modulo operation with a fixed base. | ||
Beginning with integers <tt>n</tt> and <tt>x</tt> (such that <tt>0≤x<n</tt>) and recursively adding an integer <tt>k</tt> to <tt>x</tt> and modulo'ing by <tt>n</tt> (ie. setting <tt>x=(x+k)%n</tt>) will cause <tt>x</tt>'s value to oscillate with period <tt>{{frac|n|gcd(n,k)}}</tt> (equivalently <tt>{{frac|lcm(n,k)|k}}</tt>). | |||
For a modulo base <tt>n</tt> and period <tt>p</tt>, for there to exist any integers <tt>k</tt> such that recursive addition of <tt>k</tt> has period <tt>p</tt>, <tt>p</tt> must be a factor of <tt>n</tt> (meaning <tt>n ≡ 0 (mod p)</tt>). These integers <tt>k</tt> are then the set of those <tt>0<k<p</tt> coprime to <tt>p</tt>, each multiplied by <tt>{{frac|n|p}}</tt>. The number of such values <tt>k</tt> is then given by <tt>φ(p)</tt>, where <tt>φ</tt> is [https://en.wikipedia.org/wiki/Euler's_totient_function Euler's totient function], <tt>{{OEIS|A000010|tt=tt}}</tt>.<ref group="n">These can be tabulated by running <tt>print((λ m: (λ f: '\n'.join(map(λ n: 'n='+f(m,n)+': (\n '+',\n '.join(map(λ p: p[1],filter(λ p: p[0],map(λ p: (λ t: (len(t),'p='+f(m,p)+': ('+','.join(map(str,t))+')'))(tuple(filter(λ k: n//gcd(n,k)==p,range(n)))),range(1,n+1)))))+')',range(m))))(λ n,k: ' '*(len(str(n))-len(str(k)))+str(k)))(16))</tt> in the Python terminal. The lengths of the tuples, over all values of <tt>p</tt> (instead of only nonzero ones), is the triangular array <tt>{{OEIS|A054522|tt=tt}}</tt>.</ref> | |||
There is no similar such statement about modular integer multiplication by a constant, because unlike addition of a constant, the structure of its mapping is not invariant across all inputs.<ref group="n">Also, it is neither injective (such that all numbers <tt>0≤x<n</tt> produce unique values under multiplication by <tt>k</tt> followed by modulo by <tt>n</tt>) nor surjective (such that for given <tt>n,k</tt> every value <tt>y</tt> can have an <tt>x</tt> found such that <tt>k*x%n=y</tt>). An injective function with a range of outputs equal to that of its inputs (like modular addition of a constant) is also surjective, and together they are bijective, meaning an inverse function can be defined. The modular multiplicative inverse (ie. a number <tt>y</tt> such that <tt>x*y ≡ 1 (mod n)</tt>) can be defined where <tt>x</tt> and <tt>n</tt> are coprime, and is implemented in Python's three-argument [https://docs.python.org/3/library/functions.html#pow <tt>pow</tt>] function.</ref> Due to this, similarly to cellular automata in finite planes as functions on the set of states, recursively applying a multiplication will cause integers to eventually enter one of several cycles, upon which the period depends.<ref group="n">An equivalent program to the previous one (for the cycle obtained by beginning at <tt>x=1</tt>) is <tt>print((λ m: (λ f: '\n'.join(map(λ n: 'n='+f(m,n)+': ('+','.join((λ t: map(λ p: f(m,t.count(p)),range(1,n)))(tuple(map(λ k: (λ f: f(f))(λ f: λ r,t: (λ r: t.index(r)+1 if r in t else f(f)(r,(r,)+t))(k*r%n))(1,()),range(1,n)))))+')',range(1,m))))(λ n,k: ' '*(len(str(n))-len(str(k)))+str(k)))(16))</tt>, which generates <tt>{{OEIS|A057593|tt=tt}}</tt>,{{br}}and the number of cycles counting by <tt>print((λ m: (λ f: '\n'.join(map(λ n: 'n='+f(m,n)+': '+','.join(map(λ k: f(m,(λ f: f(f))(λ f: λ c,i,o,p: (λ o: o if all(c) else f(f)(c,c.index(0),o,p+1))(o+(c[i]==p)) if c[i] else f(f)(c[:i]+(p,)+c[i+1:],k*i%n,o,p))((0,)*n,0,0,1)),range(n+1))),range(1,m))))(λ n,k: ' '*(len(str(n))-len(str(k)))+str(k)))(24))</tt> (removing the <tt>k=0</tt> column returns <tt>{{OEIS|A348888|tt=tt}}</tt>, which has [https://oeis.org/A348888/a348888.pdf a nice diagram] showing the cycles formed by different <tt>n,k</tt>).</ref> Implementations of modular exponentiation to large powers with small modulo bases can be further optimised by detecting the length of the cycle that an exponentiation process enters and finding the phase that it ends in by taking the remaining exponent (upon entry to the cycle) modulo this length, and using it as the index in the cycle. | |||
There is no similar such statement about modular integer multiplication by a constant, because unlike addition of a constant, the structure of its mapping is not invariant across all inputs.<ref group="n">Also, it is neither injective (such that all numbers <tt>0 | |||
==Relationship with bitwise operators== | ==Relationship with bitwise operators== | ||
In programming, where <tt>x,n</tt> are integer (as is usually necessary for bitwise operators) | In programming, where <tt>x,n</tt> are integer (as is usually necessary for bitwise operators), because it corresponds with truncating <tt>x</tt>'s base-<tt>2<sup>n</sup></tt> expansion to the last digit, and its binary expansion to the last <tt>n</tt> bits, <tt>x % 2<sup>n</sup> = x & 2<sup>n</sup>-1</tt>, the latter of which can be more efficient to compute. The Stanford bit-twiddling hacks explain [https://graphics.stanford.edu/~seander/bithacks.html#ModulusDivision division by <tt>1</tt> less than a power of <tt>2</tt>]. | ||
==Notable congruences== | ==Notable congruences== | ||
These provide algebraic reduction steps for forms that can arise generally in modular arithmetic problems. | These provide algebraic reduction steps for forms that can arise generally in modular arithmetic problems. | ||
* | * {{LinkWikipedia|Fermat's_little_theorem|name=Fermat's little theorem|nobullet=no|nosuffix=no}} states that for a prime <tt>p</tt> and other integer <tt>c</tt>, <tt>c<sup>p</sup> ≡ c (mod p)</tt>.<ref group="n">Being prime is sufficient but not necessary, composite <tt>p</tt> for which <tt>n<sup>p</sup> ≡ n (mod p)</tt> are called Fermat pseudoprimes to base <tt>n</tt>. The smallest composite pseudoprime <tt>p</tt> is <tt>{{OEIS|A000790|tt=tt}}(n)</tt>, which is periodic with period <tt>277# * 23#</tt>, where <tt>#</tt> is the primorial.</ref> | ||
* | * {{LinkWikipedia|Wilson's_theorem|name=Wilson's theorem|nobullet=no|nosuffix=no}} states that for an integer <tt>n</tt>, <tt>(n-1)! ≡ -1 (mod n)</tt> if <tt>n</tt> is prime, otherwise <tt>(n-1)! ≡ 0 (mod n)</tt> unless <tt>n = 4</tt>, in which case it is congruent instead to <tt>2</tt>.<ref group="n">Explained as an exercise in the MODA chapter involving placements of rooks on toroidal chessboards, and in [[Pólya_enumeration_theorem#Wilson's_theorem|the Pólya enumeration theorem article]]</ref> | ||
* {{LinkWikipedia|Lucas's_theorem|name=Lucas's theorem|nobullet=no|nosuffix=no}}: <tt>{{choose|n|k}} ≡ {{product|i{{=}}0|∞|{{choose|n<sub>i</sub>|k<sub>i</sub>}}|brac=}}<!--{{product|i{{=}}0|∞|{{choose|⌊{{frac|n|b<sup>i</sup>}}⌋%b|⌊{{frac|k|b<sup>i</sup>}}⌋%b}}|brac=}}--> (mod b)</tt>, where <tt>n<sub>i</sub></tt> is the <tt>i</tt>th base-<tt>b</tt> digit of <tt>n</tt>. | |||
===for {{LinkWikipedia|Modular_exponentiation|name=modular exponentiation|nobullet=no|nosuffix=no}} computation=== | |||
* <tt>x*y ≡ (x%n)*(y%n) (mod n)</tt>, so <tt>x<sup>p</sup>%n</tt> can be calculated as <tt>(( ... (((x%n)*x)%n)* ... )*x)%n</tt> | |||
* {{LinkWikipedia|Euler's_theorem|name=Euler's theorem|nobullet=no|nosuffix=no}}: <tt>x<sup>φ(m)</sup> ≡ 1 (mod m)</tt>, so <tt>x<sup>n</sup> ≡ x<sup>n%φ(m)</sup> (mod m)</tt>. | |||
:* If <tt>n</tt> is computed from its factorisation, <tt>n%φ(m)</tt> can be computed efficiently also | |||
:* Note that Fermat's little theorem is the special case of Euler's theorem, since for primes <tt>p</tt>, <tt>φ(p) = p-1</tt> | |||
==Uses in Conway's Game of Life== | ==Uses in Conway's Game of Life== | ||
* [[Colour]] is mod 2. | * [[Colour]] is mod 2. | ||
* [[Trombone slide]]s are mod 8. | * [[Trombone slide]]s are mod 8. | ||
| Line 38: | Line 41: | ||
* [[Conway's Game of Life: Mathematics and Construction]], Appendix A.1 Modular Congruence | * [[Conway's Game of Life: Mathematics and Construction]], Appendix A.1 Modular Congruence | ||
* [https://cp4space.files.wordpress.com/2012/09/moda-ch01.pdf Combinatorics I], the first chapter of [[Adam P. Goucher]]'s book, ''Mathematical Olympiad Dark Arts'' (that explains a great deal more about modular arithmetic than this) | * [https://cp4space.files.wordpress.com/2012/09/moda-ch01.pdf Combinatorics I], the first chapter of [[Adam P. Goucher]]'s book, ''Mathematical Olympiad Dark Arts'' (that explains a great deal more about modular arithmetic than this) | ||
* Wikipedia articles: | |||
:* {{LinkWikipedia|Chinese_remainder_theorem|name=Chinese remainder theorem|nobullet=no|nosuffix=no}}: Compute <tt>n (mod a*b)</tt> in terms of <tt>n (mod a)</tt> and <tt>n (mod b)</tt> with the extended Euclidean algorithm | |||
[[Category:Algorithms]] | [[Category:Algorithms]] | ||
[[Category:Mathematical miscellany]] | [[Category:Mathematical miscellany]] | ||
__NOTOC__ | __NOTOC__ | ||
Revision as of 13:36, 30 September 2023
| This article may require cleanup to meet LifeWiki's quality standards. |
Two numbers a,b are congruent modulo a third number n if their values are equal when integer multiples of n are added or subtracted from them such that they both lie in the range 0 ≤ x < n (an operation denoted with the % symbol).[n 1] A function returning the value of x modulo n is given in most programming languages with the % operator (ie. x%n), and according to the C specification (followed by languages like Python), modulo has the same precedence as multiplication and division, and expressions involving multiple of the same precedence adjacent without brackets will be evaluated left-to-right.[n 2]
Such equalities under the modulo operation are denoted as a ≡ b (mod n). For instance, 5 ≡ 8 (mod 3), because both of them (after multiples of 3 are subtracted) evaluate to 2. Alternatively (for integer modulo bases n), x%n is equivalent to taking x's expansion in base n and truncating the digits with greater place value than 1. Modular arithmetic is generally concerned with the behaviour of operations under the modulo operation with a fixed base.
Beginning with integers n and x (such that 0≤x<n) and recursively adding an integer k to x and modulo'ing by n (ie. setting x=(x+k)%n) will cause x's value to oscillate with period ngcd(n,k) (equivalently lcm(n,k)k).
For a modulo base n and period p, for there to exist any integers k such that recursive addition of k has period p, p must be a factor of n (meaning n ≡ 0 (mod p)). These integers k are then the set of those 0<k<p coprime to p, each multiplied by np. The number of such values k is then given by φ(p), where φ is Euler's totient function, A000010.[n 3]
There is no similar such statement about modular integer multiplication by a constant, because unlike addition of a constant, the structure of its mapping is not invariant across all inputs.[n 4] Due to this, similarly to cellular automata in finite planes as functions on the set of states, recursively applying a multiplication will cause integers to eventually enter one of several cycles, upon which the period depends.[n 5] Implementations of modular exponentiation to large powers with small modulo bases can be further optimised by detecting the length of the cycle that an exponentiation process enters and finding the phase that it ends in by taking the remaining exponent (upon entry to the cycle) modulo this length, and using it as the index in the cycle.
Relationship with bitwise operators
In programming, where x,n are integer (as is usually necessary for bitwise operators), because it corresponds with truncating x's base-2n expansion to the last digit, and its binary expansion to the last n bits, x % 2n = x & 2n-1, the latter of which can be more efficient to compute. The Stanford bit-twiddling hacks explain division by 1 less than a power of 2.
Notable congruences
These provide algebraic reduction steps for forms that can arise generally in modular arithmetic problems.
- Fermat's little theorem states that for a prime p and other integer c, cp ≡ c (mod p).[n 6]
- Wilson's theorem states that for an integer n, (n-1)! ≡ -1 (mod n) if n is prime, otherwise (n-1)! ≡ 0 (mod n) unless n = 4, in which case it is congruent instead to 2.[n 7]
- Lucas's theorem : (nk) ≡ ∏∞i=0(niki) (mod b), where ni is the ith base-b digit of n.
for modular exponentiation computation
- x*y ≡ (x%n)*(y%n) (mod n), so xp%n can be calculated as (( ... (((x%n)*x)%n)* ... )*x)%n
- Euler's theorem : xφ(m) ≡ 1 (mod m), so xn ≡ xn%φ(m) (mod m).
- If n is computed from its factorisation, n%φ(m) can be computed efficiently also
- Note that Fermat's little theorem is the special case of Euler's theorem, since for primes p, φ(p) = p-1
Uses in Conway's Game of Life
- Colour is mod 2.
- Trombone slides are mod 8.
- Filters for glider streams require certain characteristics, e.g. 8 mod 16 for Rich's p16 and 5 mod 15 or 10 mod 15 for Karel's p15.
- Phase shifters make use of modular arithmetic, e.g. 28P7.1 phase shifts once when the overall period is 1 mod 7.
- Pentadecathlon phase shifters work when the overall period is 6, 9, or 14 mod 15, depending on the mechanism. 6 corresponds to the monoicosathlon, 9 to one modification of the p54 shuttle, and 14 to the p44 pi-heptomino hassler.
- Many of the smallest known oscillators of a period that are part of infinite families rely on modular arithmetic, such as 6 bits being 45 mod 120 and the number of gliders required in a rectifier being dependent on period mod 8 and the existence of a working 22hd reflector requiring the period being 4 mod 8.
See also
- Pólya enumeration theorem (the enumeration equations must return integers, so the division in the averaging is equivalent to floordiv, meaning the output of the equivalent modulo must be 0, through which the theorems above can be proven)
Notes
- ↑ In taking x%n, when either operand is negative, programming languages' implementations differ in convention. Python ensures that the sign of the output matches that of the second input (the 'modulo base'), ie. 0≥ x%n > n if n is negative, to make x//n*n+x%n=x hold, because Python's floordiv operator // rounds towards -∞, whereas C matches the first, ie. -4%3=-1, because its integer division operator, /, returns integers but rounds towards 0, this article will use the Python convention for signed modulo.
- ↑ Without modulo or floordiv (only multiplication and division), this is equivalent to division being evaluated before multiplication, as is taught in schools.
- ↑ These can be tabulated by running print((λ m: (λ f: '\n'.join(map(λ n: 'n='+f(m,n)+': (\n '+',\n '.join(map(λ p: p[1],filter(λ p: p[0],map(λ p: (λ t: (len(t),'p='+f(m,p)+': ('+','.join(map(str,t))+')'))(tuple(filter(λ k: n//gcd(n,k)==p,range(n)))),range(1,n+1)))))+')',range(m))))(λ n,k: ' '*(len(str(n))-len(str(k)))+str(k)))(16)) in the Python terminal. The lengths of the tuples, over all values of p (instead of only nonzero ones), is the triangular array A054522.
- ↑ Also, it is neither injective (such that all numbers 0≤x<n produce unique values under multiplication by k followed by modulo by n) nor surjective (such that for given n,k every value y can have an x found such that k*x%n=y). An injective function with a range of outputs equal to that of its inputs (like modular addition of a constant) is also surjective, and together they are bijective, meaning an inverse function can be defined. The modular multiplicative inverse (ie. a number y such that x*y ≡ 1 (mod n)) can be defined where x and n are coprime, and is implemented in Python's three-argument pow function.
- ↑ An equivalent program to the previous one (for the cycle obtained by beginning at x=1) is print((λ m: (λ f: '\n'.join(map(λ n: 'n='+f(m,n)+': ('+','.join((λ t: map(λ p: f(m,t.count(p)),range(1,n)))(tuple(map(λ k: (λ f: f(f))(λ f: λ r,t: (λ r: t.index(r)+1 if r in t else f(f)(r,(r,)+t))(k*r%n))(1,()),range(1,n)))))+')',range(1,m))))(λ n,k: ' '*(len(str(n))-len(str(k)))+str(k)))(16)), which generates A057593,
and the number of cycles counting by print((λ m: (λ f: '\n'.join(map(λ n: 'n='+f(m,n)+': '+','.join(map(λ k: f(m,(λ f: f(f))(λ f: λ c,i,o,p: (λ o: o if all(c) else f(f)(c,c.index(0),o,p+1))(o+(c[i]==p)) if c[i] else f(f)(c[:i]+(p,)+c[i+1:],k*i%n,o,p))((0,)*n,0,0,1)),range(n+1))),range(1,m))))(λ n,k: ' '*(len(str(n))-len(str(k)))+str(k)))(24)) (removing the k=0 column returns A348888, which has a nice diagram showing the cycles formed by different n,k). - ↑ Being prime is sufficient but not necessary, composite p for which np ≡ n (mod p) are called Fermat pseudoprimes to base n. The smallest composite pseudoprime p is A000790(n), which is periodic with period 277# * 23#, where # is the primorial.
- ↑ Explained as an exercise in the MODA chapter involving placements of rooks on toroidal chessboards, and in the Pólya enumeration theorem article
Further reading
- Conway's Game of Life: Mathematics and Construction, Appendix A.1 Modular Congruence
- Combinatorics I, the first chapter of Adam P. Goucher's book, Mathematical Olympiad Dark Arts (that explains a great deal more about modular arithmetic than this)
- Wikipedia articles:
- Chinese remainder theorem : Compute n (mod a*b) in terms of n (mod a) and n (mod b) with the extended Euclidean algorithm