find all multiplicands and multipliers for a number

Steven D'Aprano steve+comp.lang.python at
Tue Apr 14 15:40:46 CEST 2015

On Tue, 14 Apr 2015 12:42 pm, Paul Rubin wrote:

> Steven D'Aprano <steve+comp.lang.python at> writes:
> The methods there are more "mathematical" but probably slower than what
> I posted.
> Just for laughs, this prints the first 20 primes using Python 3's
> "yield from":
>     import itertools
>     def sieve(ps):
>         p = ps.__next__()
>         yield p
>         yield from sieve(a for a in ps if a % p != 0)
>     primes = sieve(itertools.count(2))
>     print(list(itertools.islice(primes,20)))
> It's not that practical above a few hundred primes, probably.

Oh! I thought that looked familiar... that's a recursive version of David
Turner's implementation of Euler's sieve. It is very popular in Haskell
circles, usually written as:

    primes = sieve [2..]
    sieve (p : xs) = p : sieve [x | x <- xs, x `mod` p > 0]

In her paper, Melissa
O'Neill calls this the "Sleight on Eratosthenes".

According to O'Neill, it has asymptotic performance of O(N**2/(log N)**2),
which means that it will perform very poorly beyond a few hundred primes.

Here is an iterative version:

def turner():
    nums = itertools.count(2)
    while True:
        prime = next(nums)
        yield prime
        nums = filter(lambda v, p=prime: (v % p) != 0, nums)

On my computer, your recursive version is about 35% slower than the
iterative version over the first 499 primes.


More information about the Python-list mailing list