首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >最快可变数据保持器

最快可变数据保持器
EN

Stack Overflow用户
提问于 2013-03-27 16:20:17
回答 1查看 245关注 0票数 2

我最近从这里下载了位数组模块,以获得更快的素筛,但是结果很糟糕。

代码语言:javascript
复制
from bitarray import bitarray
from numpy import ones
from timeit import timeit


def sieve1(n = 1000000):
    '''Sieve of Eratosthenes (bitarray)'''
    l = (n - 1)/2; a = bitarray(l); a.setall(True)
    for i in xrange(500):
        if a[i]:
            s = i+i+3; t = (s*s-3)/2; a[t:l:s] = False
    return [2] + [x+x+3 for x in xrange(l) if a[x]]

def sieve2(n = 1000000):
    '''Sieve of Eratosthenes (list)'''
    l = (n - 1)/2; a = [True] * l
    for i in xrange(500):
        if a[i]:
            s = i+i+3; t = (s*s-3)/2; u = l-t-1
            a[t:l:s] = [False] * (u/s + 1)
    return [2] + [x+x+3 for x in xrange(l)]

def sieve3(n = 1000000):
    '''Sieve of Eratosthenes (numpy.ones)'''    
    l = (n - 1)/2; a = ones(l, dtype=bool)
    for i in xrange(500):
        if a[i]:
            s = i+i+3; t = (s*s-3)/2; a[t:l:s] = False
    return [2] + [x+x+3 for x in xrange(l)]

print timeit(sieve1, number=10)
print timeit(sieve2, number=10)
print timeit(sieve3, number=10)

以下是结果-

代码语言:javascript
复制
1.59695601594
0.666230770593
0.523708537583

bitarray筛子的速度是列表的两倍多。有人对更好的数组有建议吗?任何事情都应该比python list更快,至少我是这么想的。numpy.ones是最快的,但我不喜欢numpy,因为import需要很长时间。

我基本上是在寻找一个快速的数据持有者,它是可变的,可以容纳TrueFalse

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-03-28 05:40:43

在位数组中,位的实际设置和清除非常快。正在使构建返回列表的速度变慢。与其遍历范围,然后测试每一位,不如利用位数组对遍历位的支持。

试试这个:

代码语言:javascript
复制
def bitarray_sieve(n = 1000000):
    '''Sieve of Eratosthenes (bitarray)'''
    l = (n - 1)//2; a = bitarray(l); a.setall(True)
    for i in range(500):
        if a[i]:
            s = i+i+3; t = (s*s-3)//2; a[t:l:s] = False
    return [2] + [x+x+3 for x,b in enumerate(a) if b]

它在我的机器上运行大约0.38秒,而列表版本大约需要0.47秒。

你看过这个问题吗?

我维护gmpy2,并增加了在整数中迭代位和设置/清除位的能力。

下面的示例大约需要0.16秒。

代码语言:javascript
复制
def gmpy2_sieve2(n=1000000):
    '''Sieve of Eratosthenes (gmpy2, version 2)'''
    l = (n - 1)//2; a = gmpy2.xbit_mask(l)
    for i in range(500):
        if a[i]:
            s = i+i+3; t = (s*s-3)//2; u = l-t-1
            a[t:l:s] = 0
    return [2] + [x+x+3 for x in a.iter_set()]

现在的瓶颈是计算x+x+3。下面的解决方案不会跳过筛分2,它需要两倍的内存,但它允许立即使用位位置。在我的机器上大约需要0.08秒:

代码语言:javascript
复制
def gmpy2_sieve(limit=1000000):
    '''Returns a generator that yields the prime numbers up to limit.

    Bits are set to 1 if their position is composite.'''

    sieve_limit = gmpy2.isqrt(limit) + 1
    limit += 1

    # Mark bit positions 0 and 1 as not prime.
    bitmap = gmpy2.xmpz(3)

    # Process 2 separately. This allows us to use p+p for the step size
    # when sieving the remaining primes.
    bitmap[4 : limit : 2] = -1

    # Sieve the remaining primes.
    for p in bitmap.iter_clear(3, sieve_limit):
        bitmap[p*p : limit : p+p] = -1

    return list(bitmap.iter_clear(2, limit))

对于位的实际设置/清除,位数组比gmpy2快。而且位数组具有gmpy2所缺乏的许多功能。但是,我无法在位元中找到一个更快的方法来获得设置或清除哪个位的索引。

顺便说一句,您的基准函数sieve2()和sieve3()返回不正确的结果;您缺少if a[x]

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15663919

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档