Modular congruence: Difference between revisions

From LifeWiki
Jump to navigation Jump to search
Create (it is linked to (not by me) in 6 different pages so seemed to warrant it, though it is not very detailed (in the congruence part, at least) thus far)
 
Confocal (talk | contribs)
+
Line 26: Line 26:
<references group="n"></references>
<references group="n"></references>


==External links==
== Further reading ==
* [[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)
__NOTOC__
 
[[Category:Algorithms]]
[[Category:Algorithms]]
[[Category:Mathematical miscellany]]
[[Category:Mathematical miscellany]]
__NOTOC__

Revision as of 02:08, 9 May 2023

This article is a stub. You can help LifeWiki by expanding it.

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.

Additional arithmetic rules allow manipulation of expressions involving modulo operations, such as that x*y%n=(x%n)*(y%n)%n, with which many computations involving modulo operators can be evaluated more efficiently than explicitly, such as modular exponentiation, where calculating x**p%n allows you to "unravel" the exponentiation into a series of multiplications, and modulo the result by n with each successive multiplication.

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 n/gcd(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%p=0). These integers k are then the set of those 0<k<p coprime to p, each multiplied by n/p. The number of such values k is then given by phi(p), where phi 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) and n is known to be a power of 2, because it corresponds with truncating x's n-ary expansion to the last digit, and its binary expansion to the last log_2(n) digits, x%n=x&n-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.

See also

Notes

  1. ↑ 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.
  2. ↑ Without modulo or floordiv (only multiplication and division), this is equivalent to division being evaluated before multiplication, as is taught in schools.
  3. ↑ These can be tabulated by running print((lambda m: (lambda f: '\n'.join(map(lambda n: 'n='+f(m,n)+': (\n '+',\n '.join(map(lambda p: p[1],filter(lambda p: p[0],map(lambda p: (lambda t: (len(t),'p='+f(m,p)+': ('+','.join(map(str,t))+')'))(tuple(filter(lambda k: n//__import__('math').gcd(n,k)==p,range(n)))),range(1,n+1)))))+')',range(m))))(lambda 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.
  4. ↑ 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. Modular multiplicative inverses (ie. a number y such that x*y%n=1) can be defined where x and n are coprime, and is implemented in Python's three-argument pow function.
  5. ↑ An equivalent program to the previous one (for the cycle obtained by beginning at x=1) is print((lambda m: (lambda f: '\n'.join(map(lambda n: 'n='+f(m,n)+': ('+','.join((lambda t: map(lambda p: f(m,t.count(p)),range(1,n)))(tuple(map(lambda k: (lambda f: f(f))(lambda f: lambda r,t: (lambda 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))))(lambda n,k: ' '*(len(str(n))-len(str(k)))+str(k)))(16)), which generates  A057593,
    and the number of cycles counting by print((lambda m: (lambda f: '\n'.join(map(lambda n: 'n='+f(m,n)+': '+','.join(map(lambda k: f(m,(lambda f: f(f))(lambda f: lambda c,i,o,p: (lambda 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))))(lambda 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).

Further reading