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 listOfPrimesif __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?"
_______________________________________________ Tutor maillist - [email protected] http://mail.python.org/mailman/listinfo/tutor
