Quick Answer

The Sieve of Eratosthenes finds every prime number up to a limit N by starting with all numbers marked as potentially prime, then crossing out every multiple of each prime it finds, starting from that prime squared. Run for numbers up to 100,000, it computed all 9,592 primes in about 1.8 milliseconds, roughly 6 times faster than checking each number individually for primality by trial division, which took about 11.7 milliseconds for the same range.

The Idea: Cross Out Multiples, Not Test Each Number

The direct way to find all primes up to N is to test every number individually: for each candidate, try dividing it by every number up to its square root, and if nothing divides evenly, it is prime. This works, but it repeats the same kind of work, division and remainder checks, over and over, once per number.

The Sieve of Eratosthenes flips the approach entirely. Instead of asking "is this number prime?" one at a time, it starts by assuming everything from 2 to N is prime, then goes through numbers in order and, whenever it finds one still marked prime, crosses out every multiple of it. Whatever survives uncrossed at the end is prime, by elimination, not by individually verified division.

The insight is that crossing out multiples of 2, then 3, then 5, and so on, does all the composite-number elimination as simple addition, jumping by a fixed step, which is far cheaper per operation than the division and modulo checks trial division needs.

Why It Starts Crossing Out at i-Squared

A detail that looks arbitrary but matters for performance: when the sieve finds that i is still unmarked, so it is prime, it starts crossing out multiples of i beginning at i * i, not at 2 * i.

That is because every smaller multiple of i, 2i, 3i, ..., (i-1) * i, has already been crossed out by a smaller prime factor by the time the outer loop reaches i. For example, when the sieve reaches i = 7, the multiples 14 (2×7), 21 (3×7), 28 (4×7), and 35 (5×7) were already crossed out while processing 2, 3, and 5. The first multiple of 7 not yet eliminated by a smaller prime is 49 (7×7).

Skipping straight to i * i avoids redoing work that is already done, and it is also why the outer loop only needs to run while i * i <= N; beyond that point, every remaining composite has already been crossed out by a smaller factor.

Verified Output: Primes up to 100

Running the sieve for N = 100 produces exactly 25 primes: 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97. Cross-checked against a separate trial-division implementation over the same range, the two lists match exactly, character for character, confirming the sieve is not just fast, it is correct.

The same cross-check, extended to N = 10,000, produces 1,229 primes from both implementations, again matching exactly. Getting the same answer from two entirely different algorithms is the standard way to catch an off-by-one error in a sieve implementation, and it is worth doing before trusting your own code with a larger N, especially around the boundary condition at the limit itself. A common bug is an off-by-one in the loop bound that silently drops the limit N when it is itself prime, which only shows up as a mismatch once you compare against a second, independent implementation.

Sieve vs. Checking Each Number: A Real Timing Test

Correctness aside, the real reason to use a sieve is speed at scale. Running both implementations for N = 100,000, finding all 9,592 primes below that limit, and timing them directly: the sieve completed in about 1.8 milliseconds (averaged across three runs), while checking each number individually with trial division took about 11.7 milliseconds, roughly 6.4 times slower for the identical result.

That gap widens as N grows, because trial division's cost per number grows with the square root of that number, while the sieve's total cost stays close to N log log N across the whole range. For a single lookup, "is 97 prime?", trial division is fine and arguably simpler. The sieve wins specifically when you need all primes up to some bound, which is the situation it was designed for. This is also why the sieve is the workhorse behind precomputed prime tables in competitive programming, where the same bound gets queried thousands of times over the life of a program.

Why the Complexity Works Out So Well

The sieve's total work comes out to O(N log log N), close enough to linear in practice that it feels like a rounding error compared to trial division's roughly O(N√N) for checking every number up to N individually. It is not simply O(N) because the number of times each number gets "visited" by a crossing-out pass depends on how many distinct prime factors it has, and summing that across all numbers up to N produces the log log N term, a function that grows so slowly it is effectively a small constant for any N you would run in practice.

This is why the sieve is the default choice whenever a problem needs a full list of primes below a bound, rather than a single primality check, and why interviewers sometimes ask you to explain the log log N term specifically, to check whether you understand where the bound comes from rather than having memorized it.

Frequently Asked Questions

What is the time complexity of the Sieve of Eratosthenes? O(N log log N), which is close to linear and significantly faster than testing each number individually with trial division, especially as N grows.
Why does the sieve start crossing out multiples at i squared, not 2i? Because every smaller multiple of i has already been crossed out by a smaller prime factor by the time the sieve reaches i, so starting at i squared skips redundant work.
Is the Sieve of Eratosthenes always faster than checking each number for primality? For finding all primes up to a bound, yes, by a wide and growing margin. For checking whether one specific number is prime, trial division alone is simpler and often faster.
How much memory does the sieve use? One boolean, or bit, per number up to N, so O(N) space. For very large N where that becomes a constraint, a segmented sieve processes the range in chunks to bound memory use.
How many primes are there below 100,000? 9,592, confirmed by running both a sieve and an independent trial-division check over the same range and getting an identical count and list.