Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
批量更新Python列表的一部分_Python_List_Slice_Sieve Of Eratosthenes - Fatal编程技术网

批量更新Python列表的一部分

批量更新Python列表的一部分,python,list,slice,sieve-of-eratosthenes,Python,List,Slice,Sieve Of Eratosthenes,我已经编写了一个简单的Eratosthenes筛的实现,我想知道是否有更有效的方法来执行其中一个步骤 def eratosthenes(n): primes = [2] is_prime = [False] + ((n - 1)/2)*[True] for i in xrange(len(is_prime)): if is_prime[i]: p = 2*i + 1 primes.append(p)

我已经编写了一个简单的Eratosthenes筛的实现,我想知道是否有更有效的方法来执行其中一个步骤

def eratosthenes(n):
    primes = [2]
    is_prime = [False] + ((n - 1)/2)*[True]
    for i in xrange(len(is_prime)):
        if is_prime[i]:
            p = 2*i + 1
            primes.append(p)
            is_prime[i*p + i::p] = [False]*len(is_prime[i*p + i::p])
    return primes
我正在使用Python的列表切片来更新我的布尔值列表
is_prime
。每个元素
都是素数[i]
对应一个奇数
2*i+1

is_prime[i*p + i::p] = [False]*len(is_prime[i*p + i::p])
当我找到一个素数
p
时,我可以标记与该素数的倍数
False
对应的所有元素,并且由于小于
p**2
的所有倍数也是较小素数的倍数,我可以跳过标记。
p**2
的索引是
i*p+i

我担心计算的成本
[False]*len(is_prime[I*p+1::p])
,我尝试将其与我无法使用的其他两种策略进行比较

由于某种原因,公式
(len(is_prime)-(i*p+i))/p
(如果为正)并不总是等于
len(is_prime[i*p+i::p])
。是因为我计算的切片长度错误,还是切片中有一些微妙的地方我没有抓住

当我在函数中使用以下行时:

print len(is_prime[i*p + i::p]), ((len(is_prime) - (i*p + i))/p)
is_prime[i*p + i::p] = [False]*((len(is_prime) - (i*p + i))/p)
我得到以下输出(case
n=50
):

但是,对于较大的
n
值,这将失败,因为
xrange
不需要比long更大的值。我放弃了尝试使用itertools。把我所需要的计算进去

是否有更快更优雅的方法批量更新列表切片?我能做些什么来修复我尝试过的其他策略,以便将它们与工作策略进行比较?谢谢

使用:

切片语法将迭代您在右侧放置的任何内容;它不需要是一个完整的序列

让我们来修正这个公式。既然我们知道这是可行的,我就:

1 + (hi - 1 - lo) / step
由于
step>0
hi=stop
lo=start
,因此我们有:

1 + (len(is_prime) - 1 - (i*p + 1))//p
/
是整数除法;这将证明我们的Python 3代码是正确的,但需要2.7才能运行)

现在,把它们放在一起:

slice_len = 1 + (len(is_prime) - 1 - (i*p + 1))//p
is_prime[i*p + 1::p] = itertools.repeat(False, slice_len)

Python 3用户:请不要直接使用此公式。相反,只需编写
len(范围(开始、停止、步骤))
。这会在性能相似的情况下得到相同的结果(即O(1)),并且更易于阅读。

很好的尝试。使用timeit:>>>>timeit.timeit('eratosthenes0(10000000)',setup=“从主导入eratosthenes0,计数”,number=1)3.1473147869110107>>timeit.timeit('eratosthenes1(10000000)',setup=“从主导入eratosthenes1;从itertools导入重复,计数”,number=1)4.1984710693359375@castle-布拉沃:你发布的长度公式对我来说很合适。请提供一个错误的具体示例。使用我发布的公式:>>>eratosthenes2(50)回溯(最近一次调用):文件“”,文件“”中的第1行,eratosthenes2值中的第9行错误:尝试将大小为2的序列分配给大小为的扩展切片3@castle-好的,我修好了。到目前为止,我的原始版本仍然是最快的。对于素数
1 + (hi - 1 - lo) / step
1 + (len(is_prime) - 1 - (i*p + 1))//p
slice_len = 1 + (len(is_prime) - 1 - (i*p + 1))//p
is_prime[i*p + 1::p] = itertools.repeat(False, slice_len)