Поиск простых чисел на отрезке. Решето Эратосфена

Составлен алгоритм поиска простых чисел при помощи решета Эратосфена от 2 до n.

def erat_sieve(bound):
        if bound < 2:
            return []
        max_ndx = (bound - 1) // 2
        sieve = [True] * (max_ndx + 1)
        #loop up to square root
        for ndx in range(int(bound ** 0.5) // 2):
            # check for prime
            if sieve[ndx]:
                # unmark all odd multiples of the prime
                num = ndx * 2 + 3
                sieve[ndx+num:max_ndx:num] = [False] * ((max_ndx-ndx-num-1)//num + 1)
        # translate into numbers
        return [2] + [ndx * 2 + 3 for ndx in range(max_ndx) if sieve[ndx]]

Нужно составить алгоритм поиска простых чисел от 2^30 до 2^31. Так же существует проблема моего алгоритма. Если я ввожу

erat_sieve(1000000)

то программа работает. Если, например ввожу:

erat_sieve(1073741824)

то выдается ошибка

Traceback (most recent call last):
  File "<pyshell#1>", line 1, in <module>
    erat_sieve(1073741824)
  File "C:\Users\Администратор\Desktop\4.py", line 5, in erat_sieve
    sieve = [True] * (max_ndx + 1)
MemoryError

Помогите разобраться в чем ошибка?


Ответы (1 шт):

Автор решения: Stanislav Volodarskiy

Вот так можно уложиться в один гигабайт. Решето работает поверх bytearray (один байт на элемент). Простые числа собираются в array.array('L') (четыре байта на число):

import array
import sys


def erat_sieve(bound):
    if bound < 2:
        return []
    max_ndx = (bound - 1) // 2
    sieve = bytearray(max_ndx + 1)
    #loop up to square root
    for ndx in range(int(bound ** 0.5) // 2):
        # check for prime
        if sieve[ndx] == 0:
            # unmark all odd multiples of the prime
            num = ndx * 2 + 3
            sieve[ndx+num:max_ndx:num] = b'\x01' * ((max_ndx-ndx-num-1)//num + 1)

    sieve.pop()

    a = array.array('L')
    a.append(2)
    a.extend(ndx * 2 + 3 for ndx, v in enumerate(sieve) if v == 0)

    return a


n = int(sys.argv[1])
a = erat_sieve(n)
print(len(a))
print(a[:10])
print(a[-10:])
$ time python erat_sieve.py 1073741824
54400028
array('L', [2, 3, 5, 7, 11, 13, 17, 19, 23, 29])
array('L', [1073741651, 1073741663, 1073741671, 1073741689, 1073741717, 1073741719, 1073741723, 1073741741, 1073741783, 1073741789])

real  0m37.331s
user  0m36.704s
sys   0m0.540s
→ Ссылка