The Miller-Rabin primality test is among the fastest and most widely used primality tests in computational practice.
The algorithm of the test is as follows:
Given a large odd integer n to be tested,
compute one or more rounds of the test (see the pseudocode);
we will refer to each round as miller_rabin(n,a).a called the base;
it must be at least 2 and at most n-2.
Each round's result can be either
0 (composite) or
1 (probable prime).
If any round returns 0 (composite), then n is certain to be composite; no further rounds are needed.
If all rounds return 1 (probable prime), then n is highly likely to be prime.
In rare cases, our probable prime n might in fact be composite;
if so, n is called a strong pseudoprime a,a are called strong liars for n.
Comparing the speed of the Miller-Rabin test to a trial division test.
For small n, a brute force trial division test is much faster.
For very large prime n, the Miller-Rabin test is the winner; for example, in Google Chrome 11 on a modern 2.5GHz laptop
(a) 30 rounds of the Miller-Rabin test for a 19-digit prime take about 30 milliseconds, and
(b) 30 rounds for a 30-digit prime take about 45 milliseconds; so a single round takes about 1.0ms to 1.5ms.
The trial division test becomes extremely slow as n grows larger
(it takes 1 minute for a 19-digit prime in the same browser on the same machine);
trial division is of very little use for large prime n.
This is because the execution time of the Miller-Rabin test grows only modestly, as a polynomial function of the input size,
while the execution time of a trial division test for prime n grows very significantly, exponentially with the input size.
(This follows from the fact that, for prime n, the number of operations in a trial division test is proportional to the square root of n.
The input size in primality tests is the number of digits of n.)
Below you can run the tests yourself and compare the execution times of these JavaScript functions:
leastFactor(n) (a trial-division search for the least prime factor of the number n < 253)leastFactor_('n') (same as above, except n is expected to be a string with up to 20 digits)
miller_rabin('n','a') (a single round of the Miller-Rabin test, base a)
isPrimeMR3('n') (3 rounds of the Miller-Rabin test for bases 2,3,5)
isPrimeMR6('n') (6 rounds of the Miller-Rabin test for prime bases up to 13)
isPrimeMR10('n') (10 rounds of the Miller-Rabin test for prime bases up to 29)
isPrimeMR30('n') (30 rounds of the Miller-Rabin test for prime bases up to 113)
Caution! In the above test functions, the argument
'n' is a string (of any length) that holds the digits of n.
If, instead of a string, you pass an odd number n
less than 253 to these functions, the test will still work.
However, if you try to pass an odd number n greater than 253,
without apostrophes, the test will not work because the argument would actually turn out to be some other number
approximately equal to the desired odd number:
JavaScript/IEEE754 cannot exactly represent odd numbers that large!
The Miller-Rabin test is a probabilistic primality test because, in general, the
probable prime result at any round does not guarantee primality and, moreover, the test outcome
depends not only on n being prime but also on our choice of the bases a.
The more rounds with different bases a we perform, the higher the reliability of the test.
For smaller numbers n, a couple of rounds may be good enough; e.g. just two rounds with bases 2 and 3
are proven to correctly determine the primality of any odd n from 5 to 1373651.
For very large n, even ten rounds might still be insufficient, depending on our desired level of confidence.
For example, the following composite numbers n are known false-positives in the Miller-Rabin test (strong pseudoprimes)
for each base less than or equal to the kth prime a = 2,3,5,7...a,
the test miller_rabin(n,a) returns 1 (probable prime) even though the number n is in fact composite.
Strong pseudoprime (SPSP) to base 2: 2047 = 23*89 SPSP to both base 2 and base 3: 1373653 = 829*1657 SPSP to all bases 2 thru 5: 25326001 = 2251*11251 SPSP to all bases 2 thru 7: 3215031751 = 151*751*28351 SPSP to all bases 2 thru 11: 2152302898747 = 6763*10627*29947 SPSP to all bases 2 thru 13: 3474749660383 = 1303*16927*157543 SPSP to all bases 2 thru 19: 341550071728321 = 10670053*32010157 SPSP to all bases 2 thru 31: 3825123056546413051 = 149491*747451*34233211 SPSP to all bases 2 thru 37: 318665857834031151167461 = 399165290221*798330580441The numbers
n = 3825123056546413051 and n = 318665857834031151167461 (the last two lines)
have thirty or more liar bases a<40, including more than ten prime liar bases.
This example shows that, indeed, ten rounds may not be enough if n is this big.
Fortunately, additional rounds with more bases always allow the test to discover that
a pseudoprime n is composite.
For more information on pseudoprimes, see sequences
A014233 and
A074773 from the
Online Encyclopedia of Integer Sequences, oeis.org;
see also further references there.
Notes:
(1) Computations of the Miller-Rabin test are in modular arithmetic (mod n).
Therefore, bases greater than n, such as a = n+2,n+3,n+4...a = 2,3,4...
miller_rabin(2047,11) // 1 (probable prime) miller_rabin(2047,2058) // 1 (probable prime) 2058 = 2047 + 11 miller_rabin(2047,3) // 0 (composite) miller_rabin(2047,2050) // 0 (composite) 2050 = 2047 + 3
(2) Bases a = 1a = n-1n reported as probable prime,
i.e. these bases are strong liars for odd composite n. Examples of incorrect base choice:
miller_rabin(25,1) // 1 (probable prime) - even though 25 is composite miller_rabin(25,24) // 1 (probable prime) - even though 25 is composite miller_rabin(91,1) // 1 (probable prime) - even though 91 is composite miller_rabin(91,90) // 1 (probable prime) - even though 91 is composite
(3) Bases a = nnn misreported as composite.
That's something that never happens in the Miller-Rabin test under normal conditions.
(Once again, the normal conditions are that n should be a big odd integer;
the base a should be at least 2 and at most n-2.)
Examples of incorrect base choice of this kind:
miller_rabin(29,29) // 0 (composite) - even though 29 is prime miller_rabin(29,58) // 0 (composite) - even though 29 is prime miller_rabin(7,7) // 0 (composite) - even though 7 is prime miller_rabin(7,21 ) // 0 (composite) - even though 7 is prime
(4) JavaScript variables cannot natively represent odd numbers over 253.
Intermediate calculations in the Miller-Rabin test may involve numbers greater than that,
even if the number n itself is under 253.
Therefore, a JavaScript implementation of the Miller-Rabin test must rely on some big integer arithmetic
library in order to handle large numbers. The test implementation on this page uses
BigInt.js,
an arbitrary precision arithmetic library that has been developed and placed in the public domain by Professor Leemon Baird.
Many thanks Prof. Baird!
(5) BigInt.js 5.4 and earlier versions have a
bug in the Miller-Rabin test implementation.
Tests on this page are not affected because our function miller_rabin()
was written to call lower-level operations of BigInt.js
it does not call the affected BigInt.js functions millerRabin() and millerRabinInt().
Copyright © 1999-2011, JavaScripter.net.