[Tutor] primes
Max Noel
maxnoel_fr at yahoo.fr
Fri Mar 18 02:17:24 CET 2005
On Mar 17, 2005, at 23:54, Danny Yoo wrote:
> Hi Gregor,
>
> Here is one that's traduced... er... adapted from material from the
> classic textbook "Structure and Interpretation of Computer Programs":
> <SNIP>
Ooh, nifty.
Okay, I decided to learn how to use the timeit module, so I used it to
compare my algorithm (which, I just noticed, is a Python implementation
of the Sieve of Erastothenes) to the one Gregor originally posted
(albeit slightly optimized -- the only even prime number is 2, so
there's no need to test them), and a further optimized version of it
(stops looping at sqrt(x)).
While I was at it, I optimized my algorithm further (in both memory
usage and speed): it uses xrange and doesn't bother testing even
numbers.
Now, I did expect my algorithm to be the fastest. What I didn't
expect, though, was for the differences to be *that* massive. Letting
all three functions loose on finding all the prime numbers from 2 to
50000, I got the following results (test machine: G4 867 running Python
2.3 on OS X 10.3.8):
listPrimes: 0.508284091949 seconds # my algorithm
primeConciseOptimized: 2.18135714531 seconds # Gregor's, optimized
primeConcise: 399.251116991 seconds # Gregor's, (partially optimized)
As I suspected, when increasing the range, so do the differences.
listPrimes finds all prime numbers from 2 to 200000 in 2.55 seconds,
primeConciseOptimized in 15.81. At that point I had dropped
primeConcise, as it being O(n^3) as far as I can tell, it would have
taken ages to run. However, I thought the difference between listPrimes
and primeConciseOptimized would increase faster than that. So
primeConciseOptimized seems like the best compromise between speed and
conciseness.
Here's the (final?) version of the script I used:
#!/usr/bin/env python
import math
import timeit
def primeConcise(limit):
return [2] + [x for x in xrange(3, limit, 2) if not [y for y in [2]
+ range(3,x,2) if x%y==0]]
def primeConciseOptimized(limit):
return [2] + [x for x in xrange(3, limit, 2) if not [y for y in [2]
+ range(3,int(math.sqrt(x)), 2) if x%y==0]]
def isPrime(x, primeList):
limit = int(math.sqrt(x))
for i in primeList:
if x % i == 0:
return False
if i >= limit:
break
return True
def listPrimes(upperLimit):
listOfPrimes = [2]
for i in xrange(3, upperLimit, 2):
if isPrime(i, listOfPrimes):
listOfPrimes.append(i)
return listOfPrimes
if __name__ == '__main__':
t1 = timeit.Timer('listPrimes(50000)', 'from __main__ import
listPrimes')
t2 = timeit.Timer('primeConciseOptimized(50000)', 'from __main__
import primeConciseOptimized')
t3 = timeit.Timer('primeConcise(50000)', 'from __main__ import
primeConcise')
print t1.timeit(1)
print t2.timeit(1)
print t3.timeit(1)
-- Max
maxnoel_fr at yahoo dot fr -- ICQ #85274019
"Look at you hacker... A pathetic creature of meat and bone, panting
and sweating as you run through my corridors... How can you challenge a
perfect, immortal machine?"
More information about the Tutor
mailing list