无法理解一些主要的筛选语法

时间:2016-03-01 23:26:24

标签: python primes sieve

有人可以通过这个筛子逐行走我的路吗?我试图开发自己的筛子,但大多数更快的筛子都包含我不理解的语法(就像我已经评论过的那样)。很抱歉,如果这是一个新手问题 - 如果你有任何链接可以帮我筛选,他们将非常感激。

def rwh_primes1(n):
    """ Returns  a list of primes < n """
    sieve = [True] * (n/2) # What does the '[True]' mean?
    for i in xrange(3,int(n**0.5)+1,2):
        if sieve[i/2]: # The same complaint as in line 3, I don't understand the variable 'sieve'
            sieve[i*i/2::i] = [False] * ((n-i*i-1)/(2*i)+1) # how is sieve used here - it seems to be as a list but i'm unsure
    return [2] + [2*i+1 for i in xrange(1,n/2) if sieve[i]] # 'sieve' is confusing me here yet again.

2 个答案:

答案 0 :(得分:4)

我将每行代码的含义用斜体字表示,并在正常面部文本中添加我的注释。

sieve = [True] * (n/2)

声明一个新的局部变量sieve并将其初始化为值[True] * (n/2)该表达式是什么意思? [True]是仅包含布尔值True的单元素列表。将列表乘以数字会重复列表,因此sieve现在是n/2 - 所有 - True值的元素列表。

for i in xrange(3, int(n**0.5)+1, 2):

以2为步长开始计数,从3开始,到sqrt(n)结束。这个特殊的范围选择是Sieve算法的优化:我们可以从1到1一直计算n以1为单位,但效率较低。

if sieve[i/2]:

查看i/2列表的sieve元素。如果它是True,则继续向下if分支。作者正在使用i/2来补偿代码按2步计数的事实这样你可以使用更短的列表并使用更少的内存。

sieve[i*i/2::i] = [False] * ((n-i*i-1)/(2*i)+1)

sieve的每个第i个元素更新为False,从i * i / 2开始。 sieve[i*i/2::i]称为slice notation - 因为它出现在作业的左侧,所以此代码将更新那片sieve。右侧是list-times-number技巧的重复。它计算一个正确长度的全部False列表。

return [2] + [2*i+1 for i in xrange(1,n/2) if sieve[i]]

此代码只是将True中的False / sieve值转换为素数列表。该计算通过将每个sieve值的索引乘以2来补偿True不包含任何偶数的事实。

答案 1 :(得分:1)

假设n = 7:

    sieve = [True] * (n/2) # What does the '[True]' mean?

列出长度为n的一半的布尔值。例如,sieve = [True,True,True](因为3.5是在python2中向下舍入的分数长度)

所以xrange(3,int(n**0.5)+1,2)将是一个生成器,为我们提供这个序列:[]

    for i in 
        if sieve[i/2]: # The same complaint as in line 3, I don't understand the variable 'sieve'
            sieve[i*i/2::i] = [False] * ((n-i*i-1)/(2*i)+1) # how is sieve used here - it seems to be as a list but i'm unsure
    return [2] + [2*i+1 for i in xrange(1,n/2) if sieve[i]] # 'sieve' is confusing me here yet again.

当我们看到[i :: 2]或某些只是大海时,我们会以重复的间隔对列表进行切片。所以如果mylist包含(0..19):

>>> mylist = range(20)
>>> mylist[0::1]
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
>>> mylist[0::2]
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
>>> mylist[0::3]
[0, 3, 6, 9, 12, 15, 18]

尝试自己玩这个,以便熟悉它。 因此,在这种情况下,sieve[i*i/2::i] = [False] * ((n-i*i-1)/(2*i)+1)会将列表中的每个第i个值设置为False。