我想在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
。
我试图用位数组解决问题,但是数组的索引仍然太大。
答案 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
将为n
; 0
否则:
def is_prime(n):
return bool((is_prime_var >> (MAX-n-1)) & 1)
您可以将this excellent answer中的primes()
用作主要生成器。
thers还this answer of mine着眼于快速,高效记忆的橡皮擦筛。可能也很有趣。