最近在网上发现了这段代码:
nonprime = [j for i in range(2, 8) for j in range(i*2, 50, i)]
上面的代码似乎在计算50以下的所有非素数,但我没有得到逻辑。 我研究了python中的列表推导,并观察它使用过滤器根据条件进行过滤, 但是我无法理解两个for循环是如何计算这些非素数的。
答案 0 :(得分:3)
这个列表理解与这两个嵌套for循环的作用相同:
nonprime=[]
for i in range(2,8):
for j in range(i*2, 50,i):
nonprime.append(j)
因此在外循环中,i
在每次迭代中仅增加1,并且取值i = 2,3,4,5,6,7。
j
上的内部for循环取决于外循环。它从2*i
开始,j
在每次迭代中增加i
。
因此对于ì=2
,内部循环从j=4
开始,j
采用值j=4,6,8,...,48
。
然后ì
在外部循环中增加到3,j
采用值6,9,12,...48
请注意,nonprime
列表不会创建唯一元素,因为例如6会出现多次。
正如Bakuriu正确地指出的那样,这种方法使用了Sieve of Eratosthenes
答案 1 :(得分:2)
循环基本上是Sieve of Erathostenes,但不是删除数字而是保留它们。
在Erathostenes的筛选中,你删除倍数的已知素数"。最有效的方法是,给定一个素数p
,删除数字p*p
然后p*(p+1)
等,直到达到限制并继续下一个素数q
,并开始q*q
。
列表理解是这个的一个小变化。您可以将i*2
替换为i*i
,但仍然可以获得相同的数字(尽管重复次数较少)。
在Erathostenes的筛选中,您通常删除除2
以外的所有偶数,然后使用2*i
作为范围的步骤,因为您只需要考虑奇数的素数。显然,如果你想获得所有非素数,那么这不是真的,以便"优化"不起作用。
答案 2 :(得分:2)
这个答案的关键在于数学:
If a number n>1 is not prime, then it has a prime factor <= sqr(n)
现在我们要解释逻辑。请注意sqrt(50) < 8
,这是第一个range
的限制。
我们可能会将嵌套列表理解重写为常规循环。我们可以使用set
而不是列表,这将包含不必要的重复元素:
res = set()
for i in range(2, 8):
for j in range(i*2, 50, i):
res.add(j)
外部循环迭代所有i < sqrt(50)
。
对于每个i
,内部循环迭代所有i
的倍数小于50。
通过上述数学陈述,我们得到的所有非素数都在50以下。这是正确的,因为我们正在耗尽所有素因子&lt; = sqrt(50)。
答案 3 :(得分:0)
这是该代码的非列表理解版本:
nonprime = []
for i in range(2, 8):
for j in range(i*2, 50, i):
nonprime.append(j)
一步一步:
for i in range(2, 8):
到目前为止,非常简单。这将返回数字2到7,当它到达8时停止。在此循环的第一次迭代中,i = 2
。
for j in range(i*2, 50, i):
现在我们正在创建一个内循环。我们将i
替换为2,这样我们就可以看到它在外部循环的第一次迭代中所做的事情。
for j in range(2*2, 50, 2):
或
for j in range(4, 50, 2)
这将返回一个以4开头的数字列表,每次加注2(6,8,10),当它达到50时停止。如果你在nonprime
查看结果,你可以看到我会看到这些数字。
外循环的下一次迭代i = 3
。所以:
for j in range(i*2, 50, i):
变为:
for j in range(3*2, 50, 3):
或者:
for j in range(6, 50, 3):
从6开始,我们继续添加3并在到达50时停止。您会在nonprime
这就是所有这些代码正在做的事情。正如@Bakuriu所指出的那样,这基本上是Sieve of Erathostenes,但这是另一个主题。
答案 4 :(得分:0)
它基本上计算范围(2,8)低于50的所有值的倍数。它将包含重复的值。
# iterates over values in this range [2, 7]
for i in range(2, 8)
# iterates over multiples of i lower than 50
for j in range(i*2, 50, i)
结果如下:
[ 4, 6, 8, ... # multiples of 2 lower than 50
6, 9, 12, ... # multiples of 3 lower than 50
(...)
14, 21, 28, ... # multiples of 7 lower than 50
]