patternpythonMinor
Python prime number generator
Viewed 0 times
numberprimepythongenerator
Problem
I'm trying to get a better grasp on generators in Python because I don't use them enough (I think generators are cool). To do so I wrote a generator for prime numbers:
This works as expected but if I use list comprehension to create a list of primes using this generator it's really slow when compared to sieve function that generates the same list:
I'm assuming that this is not the intended purpose of a generator, but I thought I would see if anyone can think of a way to make this faster.
def primes():
x = 2
while True:
for y in xrange(2, x/2 + 1):
if x % y == 0:
break
else:
yield x
x = x + 1This works as expected but if I use list comprehension to create a list of primes using this generator it's really slow when compared to sieve function that generates the same list:
[prime.next() for i in xrange(1000)] # exectues in 0.212 sec, sieve in 0.001 secI'm assuming that this is not the intended purpose of a generator, but I thought I would see if anyone can think of a way to make this faster.
Solution
Stylistically, using
I also prefer using the
Algorithmically, the sieve has a big advantage because it uses the previously calculated primes to make checking the next prime faster. You don't need to check every number for divisions, just the primes. You could do something like:
Performing the division will still be more expensive than what the sieve has to do. You could implement the entire sieve algorithm in a generator. But I'm not sure what purpose that would serve.
Generally, generators work nicely when you don't have to maintain a lot of state for each value generated. But that's not the case for primes.
itertools.count() rather than implementing your own counter would be a bit cleaner.I also prefer using the
any() over a generator rather than an explicit for loop with a break and else. I think it's easier to follow.Algorithmically, the sieve has a big advantage because it uses the previously calculated primes to make checking the next prime faster. You don't need to check every number for divisions, just the primes. You could do something like:
past_primes = []
for x in itertools.count(2):
if not any(x % prime == 0 for prime in past_primes):
past_primes.append(x)
yield xPerforming the division will still be more expensive than what the sieve has to do. You could implement the entire sieve algorithm in a generator. But I'm not sure what purpose that would serve.
Generally, generators work nicely when you don't have to maintain a lot of state for each value generated. But that's not the case for primes.
Code Snippets
past_primes = []
for x in itertools.count(2):
if not any(x % prime == 0 for prime in past_primes):
past_primes.append(x)
yield xContext
StackExchange Code Review Q#6696, answer score: 7
Revisions (0)
No revisions yet.