The sieve of Eratosthenes looks like this:
def sieve(n): primality_flags = [True]*(n+1) flags[0] = flags[1] = False primes = [] for i, flag in enumerate(primality_flags): if flag: primes.append(i) for j in xrange(2*i, n+1, i): flags[i] = False
It processes each number once when the outer loop reaches it, and once for each number that divides it. About 1/2 the number is divided by 2, about 1/3 is divided by 3, etc .; asymptotically, the average number of times that each number is processed is 1 + the sum of the inverse numbers of primes to n. This sum is about log(log(n)) , so the sieve has an asymptotic time complexity of O(n*log(log(n))) , assuming that arithmetic is constant time. This is really good.
Your function does not do this. Your filter looks at each element in numbers , regardless of whether it is divisible by prime . Each element is processed for each prime number to the first number that divides it, and processing a prime p removes about 1 / p of the numbers elements. Let a sequence of primes be p [0], p [1], p [2], etc., and let a sequence of sizes numbers be n [0], n [1], n [2], etc. ., we have the following approximate recurrence:
n[0] = upperBound - 1 n[1] = n[0] * (p[0]-1)/p[0] n[2] = n[1] * (p[1]-1)/p[1] ... n[k+1] = n[k] * (p[k]-1)/p[k]
and your algorithm takes time roughly proportional to the sum of the values ββof n until numbers is empty. I did not analyze the behavior of this series, but the calculation shows that growth is much worse than O(n*log(log(n))) .
source share