[Tutor] primes - sieve of odds
C Smith
smichr at hotmail.com
Thu Mar 24 00:17:06 CET 2005
On Wednesday, Mar 23, 2005, at 04:00 America/Chicago,
tutor-request at python.org wrote:
> Now it would be fine to have an *equally fast*
> infinite prime number generator.
>
> Has anybody any suggestions?
>
I think when you add the condition of it being an infinite generator,
you are changing the rules and can't end up with something as fast.
What makes the sieve so fast is that we are generating all the primes
in a given range using a very simple "strike out" method. In the
infinite generator scenario, you will get all the primes up to n with
the sieve and can yield those back, but at some point you will have to
stop and get "the next one." To get the next one you will have to pick
a range in which a next prime is likely to be found. The previous
primes can be used to clear out this range.
What follows is an attempt based on the previous tutor-evolved sieve
that extends the range in which to find the next prime by a factor of 2
over the last known prime. A similar algorithm is on ASPN (I bellieve),
under
Space-efficient version of sieve of Eratosthenes.
D. Eppstein, May 2004
It's slower than the sieve but about twice as fast as Eppstein's up to
1,000,000. I'll leave it to someone else to see when it finally blows
up :-) The output of primes was checked through 1,000,000 against
Eppstein's generator without error.
/c
###
def esieve():
'''extended sieve generator that returns primes on each call. When the
end of the
existing list is reached, more primes are sought in the range that
extends to
twice the last known prime. The known primes are used to clear out this
extended
range using the Sieve of Eratosthenes.'''
# get started with primes less than 100; you need at least [2, 3]
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]
i=0
while 1:
yield primes[i]
i+=1
if i==len(primes): #extend range
minn=primes[-1]+2 #this is an odd number
maxx=2*minn+1 #there should be a prime in this range; +1
makes it odd
sqrt=int(maxx**.5) #don't use primes bigger than this
length = (maxx-minn)//2 #this is used for computing the
crossing out None values
nums=range(minn,maxx+1,2) #here is the range in which a
primes will be found
for p in primes:
if p>sqrt:break
j=minn%p #find out where the striking out should start
if j<>0:
j=(p-j) #if evens were present, this is where to
start, but...
if (minn+j)%2==0:j+=p #if it lands on an even, go
to the next one
j//=2 #and now account for the fact that evens
aren't present
nums[j::p]=[None]*(1+(length-j)//p) #cross out
multiples of p
x=filter(None,nums) #clean up the range
assert len(x)>0 #there should be a prime in here, but check
anyway
primes.extend(x) #add these to the existing primes and
continue yielding
###
More information about the Tutor
mailing list