Number Theory & Algebra contents
Primality Tests
Decide whether a single large number is prime: trial division, the Fermat test, and the deterministic Miller-Rabin test for 64-bit integers.
Read first: Sieve of Eratosthenes, Binary Exponentiation
The sieve tells you about every number up to . When you have one (or a few) huge numbers, say up to , you need a test that works on a single number.
Trial division
Check every candidate divisor up to (a composite always has a divisor that small):
from math import isqrt
def is_prime_trial(n):
if n < 2:
return False
if n % 2 == 0:
return n == 2
for d in range(3, isqrt(n) + 1, 2):
if n % d == 0:
return False
return True
assert [p for p in range(30) if is_prime_trial(p)] == [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
assert is_prime_trial(10 ** 9 + 7) and not is_prime_trial(10 ** 9 + 9 * 7)The complexity is . Fine up to about for a single query, hopeless for ( divisions).
Fermat primality test
Fermat's little theorem: if is prime and , then
So if we find some base with , then is definitely composite. If it holds, is probably prime. Thanks to binary exponentiation, each base costs :
import random
def fermat_test(n, rounds=10):
if n < 4:
return n in (2, 3)
for _ in range(rounds):
a = random.randrange(2, n - 1)
if pow(a, n - 1, n) != 1:
return False
return True
assert fermat_test(1_000_000_007)
assert not fermat_test(1_000_000_007 * 3)The catch: Carmichael numbers such as satisfy for every base coprime to , so Fermat is fooled except for bases sharing a factor with .
assert all(pow(a, 560, 561) == 1 for a in range(2, 561) if __import__("math").gcd(a, 561) == 1)That is why Fermat is rarely used on its own.
Miller-Rabin test
Miller-Rabin strengthens Fermat. Write with odd. If is prime, then for any base (not divisible by ), one of these holds:
The reason is that in the field the only square roots of are , so the chain can reach only from or from .
A base for which the condition fails is a witness that is composite. For composite , at least of all bases are witnesses, so random bases give an error probability of at most after rounds.
def is_composite_witness(n, a, d, s):
"""True if base a proves that n is composite."""
x = pow(a, d, n)
if x == 1 or x == n - 1:
return False
for _ in range(s - 1):
x = x * x % n
if x == n - 1:
return False
return True
def is_probable_prime(n, rounds=20):
if n < 2:
return False
for p in (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37):
if n % p == 0:
return n == p
d, s = n - 1, 0
while d % 2 == 0:
d //= 2
s += 1
return not any(
is_composite_witness(n, random.randrange(2, n - 1), d, s) for _ in range(rounds)
)Deterministic version for 64-bit numbers
Random bases are not even needed. It has been verified that testing the first twelve primes as bases gives a correct answer for all , which covers every 64-bit integer:
BASES = (2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37)
def is_prime(n):
"""Deterministic primality test, correct for all n < 3.3e24."""
if n < 2:
return False
for p in BASES:
if n % p == 0:
return n == p
d, s = n - 1, 0
while d % 2 == 0:
d //= 2
s += 1
return not any(is_composite_witness(n, a, d, s) for a in BASES)
# agrees with the sieve on every number below 100000
from math import isqrt
sieve = bytearray([1]) * 100_001
sieve[0] = sieve[1] = 0
for i in range(2, isqrt(100_000) + 1):
if sieve[i]:
sieve[i * i :: i] = bytes(len(range(i * i, 100_001, i)))
assert all(is_prime(n) == bool(sieve[n]) for n in range(100_001))
# Carmichael numbers and strong pseudoprimes are rejected
assert not is_prime(561) and not is_prime(41041)
assert not is_prime(3_215_031_751) # passes the bases 2, 3, 5, 7 but is composite
# large primes
assert is_prime(2 ** 61 - 1) and is_prime(10 ** 18 + 9) and is_prime(10 ** 9 + 7)
assert not is_prime((2 ** 31 - 1) * (2 ** 61 - 1))Each base costs one modular exponentiation with multiplications, so a test takes about multiplications: microseconds to a fraction of a millisecond, and for numbers below you can even use just the seven bases .
Which test should I use?
| Situation | Choice |
|---|---|
| all primes up to | sieve |
| one number | trial division |
| any number up to and beyond | deterministic Miller-Rabin |
| a huge number where a tiny error probability is acceptable | Miller-Rabin with random bases |
Practice problems
Practice
Apply this on the platform and get an instant verdict.