处理Eratosthenes筛选的极大清单

时间:2014-11-27 01:47:08

标签: python python-3.x

在我的python代码中,我有以下行

vals = [True] * n

n是一个较小的数字时,此代码有效但我希望在n ~ 100,000,000没有获得MemoryError

的情况下工作

我甚至尝试使用这样的词典,但它仍然无法正常工作

vals = {}
for i in range(0, n):
    vals[i] = True

有什么建议吗?

修改 对于那些你想知道我想要做什么的人。我正在尝试实现Sieve of Eratosthenes算法来生成素数。 vals变量会跟踪稍后在算法

中找到的复合数字

编辑2 我不这么认为我可以使用生成器,因为我需要稍后更改值,如下所示:

vals = [True] * n
for i in range(0, n):
    if condition:
        vals[i] = False

5 个答案:

答案 0 :(得分:3)

使用numpy您可以处理大型列表:

import numpy as np

vals = np.ones(100000000,bool)
print(vals)
# [ True  True  True ...,  True  True  True]

答案 1 :(得分:1)

不要将所有数据保存在内存中,只保留当前所需的数据或保留其他表示形式,以便即时生成。

在这种情况下,您应该使用“稀薄的空气”表示:

  • 保留到目前为止找到的所有素数列表
  • 对于每个素数,保留上次触发此素数过滤器的复合数
  • 然后,一次走数字轴并检查每个prime-last_multiple对,如果当前数字是下一个多个

或者,您可以将数据卸载到磁盘,例如使用偏移来访问元素(这将是相当慢的)或编写具有类似列表的接口的类,该类将使用磁盘和缓存,在需要时加载和卸载数据(mmap是IMO的良好支持选择)。

答案 2 :(得分:0)

您可以使用发电机

vals = lambda n: (True for _ in range(n))

编辑:因为OP要求实施numpy

n = 100000000
prime = lambda n: list(filter(lambda x: (x % np.arange(2, 1+int(math.sqrt(x)))).all(), range(2, n+1)))

答案 3 :(得分:0)

您可能想要使用生成器:

def vals():
    for i in range(0, n):
        yield True

为了与Python 2.x兼容,最好使用xrange

try:
    xrange
except NameError:
    xrange = range

def vals():
    for i in xrange(0, n):
        yield True

否则,如果使用较旧的解释器运行,您的程序将无声地耗尽资源。

答案 4 :(得分:-2)

检查这些:

http://stromberg.dnsalias.org/~strombrg/bits_mod/

http://stromberg.dnsalias.org/~strombrg/sieve/

第一种是使用至少31位多个整数的位数组类型。

第二个是基于该位阵列类型的筛子。

如果你仍然需要一些不适合内存的东西,你可能会考虑修改bits_mod来使用mmap,例如:http://stromberg.dnsalias.org/~strombrg/drs-bloom-filter/

这里有一些时间信息,使用pypy3 2.4.0,如果你决定走numpy路线,但仍然好奇pypy3可以做什么:

$ time ./sieve 100000000 > /dev/null
Creating bit array
Clearing multiples of 2
Clearing multiples of 3
Clearing multiples of 5
Clearing multiples of 7
...
Clearing multiples of 9931
Clearing multiples of 9941
Clearing multiples of 9949
Clearing multiples of 9967
Clearing multiples of 9973

real    1m10.749s
user    1m8.133s
sys     0m2.405s