如何在2 ^ 63-1中用Python获取素数集合

时间:2018-11-16 08:12:12

标签: python arrays primes

我想在Python中获得一个2 ^ 63-1内的质数集,我在网上看到了以下代码:

limit = 2**63 - 2
p = [True] * (limit + 1)
# p = bitarray(limit + 1)
p[0] = p[1] = False
for i in range(2, int(math.sqrt(limit) + 1)):
    if p[i]:
        for j in range(i * i, limit + 1, i):
            p[j] = False
prime = [i for i in range(limit + 1) if p[i]]
print(prime)

但是,当我运行该程序时,编译器会抱怨can not fit 'int' into an index-sized integer。 我试图用位数组解决问题,但是数组的索引仍然太大。

3 个答案:

答案 0 :(得分:1)

您可以使用sympy:

import sympy

print(list(sympy.primerange(0,2**63-1)))

但是由于2 ^ 63很大,这将需要一些时间。

答案 1 :(得分:1)

您可以使用以下代码。它结合使用Eratosthenes筛和生成器功能,以减少此算法的内存使用量。此外,还利用了鲜为人知的事实,即每个素数> 4都可以写为6 * n±1。

import math

limit = 2 ** 63 - 1

def isPrim(n, belowPrims):
    limit = int(math.sqrt(n))
    for prim in belowPrims:
        if prim > limit: break
        if n % prim == 0: return False 
    return True

def calcPrims():
    yield 2
    yield 3
    toTest, nextN = [], 6
    while True:
        p1 = nextN - 1
        if isPrim(p1, toTest):
            yield p1
            toTest.append(p1)
        p2 = nextN + 1
        if isPrim(p2, toTest):
            yield p2
            toTest.append(p2)
        nextN += 6

for prim in calcPrims():
    if prim > limit:
        break
    print(prim)

修改

此处的链接https://primes.utm.edu/notes/faq/six.html简要说明了为什么每个素数都可以6 * n±1的形式写。

答案 2 :(得分:0)

如果您有某种primes()生成器,则可以执行以下操作:

is_prime_var = 0

MAX = 1 << 5
last_p = 0
for p in primes():
    if p > MAX:
        break
    print(p, p-last_p)
    is_prime_var <<= (p - last_p)
    is_prime_var |= 1
    last_p = p
is_prime_var <<= (MAX - last_p - 1)

现在素数的位置以相反的顺序存储在整数is_prime_var中。

然后,如果(is_prime >> (MAX-n-1)) & 1为质数,则表达式1将为n0否则:

def is_prime(n):
    return bool((is_prime_var >> (MAX-n-1)) & 1)

您可以将this excellent answer中的primes()用作主要生成器。

thers还this answer of mine着眼于快速,高效记忆的橡皮擦筛。可能也很有趣。