The decision table
| Range | Method | Cost |
|---|---|---|
| Single | trial division to | |
| Single | deterministic Miller-Rabin | |
| All primes up to | sieve of Eratosthenes | |
| All primes up to | segmented sieve | , memory |
| Primes in with small | segmented sieve | |
| Mersenne numbers | Lucas-Lehmer | |
| Cryptographic sizes, need a proof | ECPP | heuristic |
| Theoretical interest | AKS |
Trial division
bool isPrime(long long n) {
if (n < 2) return false;
for (long long i = 2; i * i <= n; i++)
if (n % i == 0) return false;
return true;
}Only test 2, 3, then to cut the work by a factor of 3. Fine up to ; hopeless beyond.
Deterministic Miller-Rabin for 64-bit
The practical answer. Testing the bases is provably correct for every . See Miller-Rabin.
for (u64 a : {2,3,5,7,11,13,17,19,23,29,31,37})
if (witness(a, d, n, s)) return false;
return true;Smaller sufficient sets exist for smaller bounds: for , for .
Sieve of Eratosthenes
vector<bool> sieve(int n) {
vector<bool> isComposite(n + 1, false);
for (int i = 2; (long long)i * i <= n; i++)
if (!isComposite[i])
for (int j = i * i; j <= n; j += i) isComposite[j] = true;
return isComposite;
}Starting the inner loop at (not ) is the standard optimisation — smaller multiples were already marked.
Linear sieve () additionally gives the smallest prime factor of every number, which makes factorisation per query:
vector<int> spf(n + 1, 0), primes;
for (int i = 2; i <= n; i++) {
if (!spf[i]) { spf[i] = i; primes.push_back(i); }
for (int p : primes) {
if (p > spf[i] || (long long)i * p > n) break;
spf[i * p] = p;
}
}Each composite is marked exactly once — by its smallest prime factor.
Segmented sieve
To find primes in with up to but :
- Sieve primes up to .
- Allocate a boolean array of size .
- For each small prime , mark multiples starting at .
time, memory.
Facts about prime density
| Quantity | Value |
|---|---|
| , primes below | |
| 78 498 | |
| 50 847 534 | |
| Gap between consecutive primes near | on average; max gap below is 1476 |
| Probability a random is prime | |
| Number of prime factors of (distinct) | ; on average |
| Largest number of divisors below | 103 680 |
The ” average gap” is worth remembering: to find a prime near , test about 40 candidates.
Common pitfalls
Three recurring bugs
- is not prime, and must be handled before anything else.
i * i <= noverflows when is near — usei <= n / ior__int128.- The Fermat test alone is wrong. Carmichael numbers (561, 1105, 1729, …) pass it for every coprime base. Miller-Rabin’s square-root check is what fixes this.
Related
- Integer Factorization — the harder problem
- Sieve Techniques — sieving for things other than primality
- Pollard’s Rho — pair with Miller-Rabin to factor 64-bit numbers
See also: Miller-Rabin · Sieve of Eratosthenes · Integer Factorization