While we looked at using the GCD for devising a Las Vegas-type algorithm to test for the primality of a number in a previous entry, we saw that actually testing the number against a list of primes (therefore assuming we have an arbitrarily long list of primes), one prime at a time, is much faster.
The GCD method, for divisor , tests a number in steps, but we haven’t determined the complexity of the other method. Let’s do that now.
Let’s recapitulate: The expected complexity (upper bounded by) is:
with terms. How does it work? The algorithm does one iteration in all cases, with one factor. With two factors, it checks the first, and there’s a chance that it doesn’t stop there because the test failed; it continues another iteration. The probability that it continues after testing 2 is , because half of the numbers caused the algorithm to stop at the first iteration. Of the remaining, an iteration cost of at least 1 is incurred (testing the next factor) and there’s a probability (compound, that’s why it’s a product form) of that 3 did not divide it; yielding yet another iteration with probability incurring cost of at least 1 to test for five, with the probability of that it continues.
Written as above, the complexity is rather cumbersome. Let’s rewrite it:
Note that the fractions are not reduced, that is, you have instead of . At first, I had the reflex of simplifying the fractions too, but it sometimes hinders insight. In this form, we can use the numerators in Sloane’s On-Line Encyclopedia of Integer Sequences to find that it’s A005867. Doing the same with the denominators, we find that they’re A002110, the primorials.
Therefore the numerators are given by:
where is the jth prime number, starting at . The series of denominators, the primorials are given by:
This expression is correct but it’s unwieldy. If we want to approximate it, we can notice (well, after some work, it just doesn’t show up by itself!) that:
and, using that result, we have
where is the nth generalized harmonic number of order .
The GCD-based algorithm is where is the primorial we use for testing. The naïve algorithm is , the index of the primorial! It’s basically a algorithm when we measure both against . That’s why it’s faster.
Above, I made you notice that I did not use simplified fractions, despite it being too often my first reflex to do so. Simplifying prematurely may yield very strange looking series, and prevent you from finding anything useful in Sloane’s Encyclopedia. Because chances are, someone before you managed to create that same series—maybe in an entirely different context—and added it to the database. And it’s especially useful when you work with primes, a notoriously difficult subject.