I know the Miller–Rabin primality test is probabilistic. However I want to use it for a programming task that leaves no room for error.
Can we assume that it is corr
Miller–Rabin is indeed probabilistic, but you can trade accuracy for computation time arbitrarily. If the number you test is prime, it will always give the correct answer. The problematic case is when a number is composite, but is reported to be prime. We can bound the probability of this error using the formula on Wikipedia: If you select k
different bases randomly and test them, the error probability is less than 4-k. So even with k = 9
, you only get a 3 in a million chance of being wrong. And with k = 40
or so it becomes ridiculously unlikely.
That said, there is a deterministic version of Miller–Rabin, relying on the correctness of the generalized Riemann hypothesis. For the range u
up to 264, it is enough to check a = 2, 3, 5, 7, 11, 13, 17, 19, 23
. I have a C++ implementation online which was field-tested in lots of programming contests. Here's an instantiation of the template for unsigned 64-bit ints:
bool isprime(uint64_t n) { //determines if n is a prime number
const int pn = 9, p[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23 };
for (int i = 0; i < pn; ++i)
if (n % p[i] == 0) return n == p[i];
if (n < p[pn - 1]) return 0;
uint64_t s = 0, t = n - 1;
while (~t & 1)
t >>= 1, ++s;
for (int i = 0; i < pn; ++i) {
uint64_t pt = PowerMod(p[i], t, n);
if (pt == 1) continue;
bool ok = 0;
for (int j = 0; j < s && !ok; ++j) {
if (pt == n - 1) ok = 1;
pt = MultiplyMod(pt, pt, n);
}
if (!ok) return 0;
}
return 1;
}
PowerMod
and MultiplyMod
are just primitives to multiply and exponentiate under a given modulus, using square-and-{multiply,add}.