I am making a Sieve of Eratosthenes implementation in Python. A problem that occurs is not all primes appear (mainly the lower numbered ones).

Here is my code:

def prevPrimes(n):
    from math import sqrt
    from time import time
    start = time()
    if type(n) != int and type(n) != long:
        raise TypeError("Arg (n) must be of <type 'int'> or <type 'long'>")
    if n <= 2:
        raise ValueError("Arg (n) must be at least 2")
    limit, x, num, primes = sqrt(n), 2, {}, []
    for i in range(1, n+1):
        num[i] = True
    while x < limit:
        for i in num:
            if i%x==0:
                num[i] = False
        x += 1
    for i in num:
        if num[i]:
            primes.append(i)
    end = time()
    primes = sorted(primes)
    print round((end - start), 2), ' seconds'
    return primes

If I input >>> prevPrimes(1000), I would expect the result to start out as: [2, 3, 5, 7, 11, 13, 17] etc. However, this is what it looks like: [1, 37, 41, 43, 47, #more numbers].

I know that the issue lies in the fact that it is stating the 'original' primes (2, 3, 5, 7, 11, 13, 17, etc.) as False because of the way my program checks for the primes. How can I avoid this? Thanks in advance :)

有帮助吗?

解决方案

So that wasn't an actual SoE implementation, one I wrote a while ago is below.

number_primes = 10
prime_list = [True]*number_primes

for i in range (2, number_primes):    #check from 2 upwards
  if prime_list[i]:                   #If not prime, don't need to bother about searching
    j = 2
    while j*i < number_primes:        # Filter out all factors of i (2...n * prime)
      prime_list[j*i] = False
      j+=1

其他提示

Sometimes when you iterate through num, x is equal to i, so i % x equals 0, and i gets marked as a non-prime.

You need to add if not x == i: somewhere in your while loop, e.g.:

while x < limit:
        for i in num:
            if not x == i:
                if num[i] and i%x==0:
                    num[i] = False

First, the answer to your specific question. You are discarding the primes less than the square root of n. The easiest fix is to change the line num[i] = False to num[i] = (not x == i) at the end of your inner loop (I think that works, I haven't tested it).

Second, your algorithm is trial division, not the Sieve of Eratosthenes, and will have time complexity O(n^2) instead of O(n log log n). The modulo operator gives the game away. The simplest Sieve of Eratosthenes looks like this (pseudocode, which you can translate into Python):

function primes(n)
  sieve := makeArray(2..n, True)
  for p from 2 to n step 1
    output p
    for i from p+p to n step p
      sieve[i] := False

There are ways to improve that algorithm. If you're interested in programming with prime numbers, I modestly recommend this essay, which includes an optimized Sieve of Eratosthenes with implementation in Python.

import time

def primes_sieve1():

limitn = int(raw_input("Please enter an upper limit ")) +1
start = time.clock()
primes = {
    }

for i in range(2, limitn):
    primes[i] = True

for i in primes:
    factors = range(i,limitn, i)
    for f in factors[1:]:
        primes[f] = False

end = time.clock()
print "This took ",end-start," seconds"
return [i for i in primes if primes[i]==True]

primes_sieve1()

Instead of using division this code takes the multiples of all numbers less than the root of the limit and changes them to false. This is somewhat quicker as it does not involve dividing every number by some other number.

Also below 1000 the situation occurs whereby a prime will be modulo ed by itself to give 0 and so the program will think it is false. Since the sqrt(1000) is roughly 31, primes less than 31 will be affected.

For example on the 7th loop of "while x < limit" the situation occurs such that: 7%7 == 0 and so 7 will appear to be false in your program. This will happen for all primes less than the limit of the "while x < limit" loop as x will at some point be a prime you are trying to find.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top