今天,我为一个主筛编写了一个简短的脚本,我正在寻求改进它。我对python和编程很新,所以我想知道:在涉及大数字列表的程序中减少内存使用量的好方法是什么?这是我的示例脚本:
def ES(n):
A = list(range(2, n+1))
for i in range(2, n+1):
for k in range(2, (n+i)//i):
A[i*k-2] = str(i*k)
A = [x for x in A if isinstance(x, int)]
return A
这个脚本将列表中的所有复合体A转换为字符串,然后返回剩余整数列表,这些整数都是素数,但它运行A [i * k-2] = str(i * k)三12号的时间,因为它经历了2的所有倍数,然后是3和6的倍数。随着这样的事情的发生,当存储这么大的列表时,我很快就碰到了一堵砖墙,它崩溃了。任何建议将不胜感激!提前谢谢。
编辑:我不知道这是否有所作为,但我使用的是Python 3.3
答案 0 :(得分:2)
首先,你使用一种非常奇怪,低效的方式来记录某些东西是否是复合的。您不需要存储数字的字符串表示,甚至数字本身。您可以使用大量布尔值,如果prime[n]
为素数,则n
为真。
其次,没有理由担心如果简化索引,就会在列表的开头浪费一些空间。与列表其余部分占用的空间相比,它很小,更不用说你使用的所有字符串和整数。这就像为你的30万美元汽车节省3美元油漆。
第三,range
采用step
参数来简化循环。
def sieve(n):
"""Returns a list of primes less than n."""
# n-long list, all entries initially True
# prime[n] is True if we haven't found a factor of n yet.
prime = [True]*n
# 0 and 1 aren't prime
prime[0], prime[1] = False, False
for i in range(2, n):
if prime[i]:
# Loop from i*2 to n, in increments of i.
# In other words, go through the multiples of i.
for j in range(i*2, n, i):
prime[j] = False
return [x for x, x_is_prime in enumerate(prime) if x_is_prime]
答案 1 :(得分:0)
您可以使用生成器。而不是使用大型列表。
def ESgen():
d = {}
q = 2
while 1:
if q not in d:
yield q
d[q*q] = [q]
else:
for p in d[q]:
d.setdefault(p+q,[]).append(p)
del d[q]
q += 1
要使用生成器获取第一个n
素数列表,您可以执行以下操作:
from itertools import islice
gen = ESgen()
list(islice(gen, n))
如果您只想检查数字是否为素数,set
比list
更快:
from itertools import islice
gen = ESgen()
set(islice(gen, n))