简体   繁体   English

在 Python 中使用模数查找素数

[英]Finding Primes with Modulo in Python

I have been sweating over this piece of code -- which returns all the primes in a list:我一直在为这段代码感到汗流浃背——它返回列表中的所有素数:

primes = range(2, 20) 
for i in range(2, 8): 
     primes = filter(lambda x: x == i or x % i, primes)

print primes

It works... but I don't understand the role " x == i or x % i " plays in the whole thing.它有效......但我不明白“ x == i or x % i ”在整个过程中的作用。

I also don't understand why the second range is only 2 to 7.我也不明白为什么第二个范围只有 2 到 7。

I even created a Python implementation of the Sieve of Eratosthenes, hoping that might give me some insight, but it didn't.我什至创建了埃拉托色尼筛的 Python 实现,希望这能给我一些见解,但它没有。

When I remove the x % i component, I would expect this code to give me the numbers common to both sets, but it does not:当我删除x % i组件时,我希望这段代码能给我两个集合共有的数字,但它没有:

nums = [2, 20] 
for i in range(2, 8): 
     nums = filter(lambda x: x == i, nums)

print nums

Why is this?为什么是这样?

Likewise, when I remove the x == i component, it returns the prime numbers from 11 to 19.同样,当我删除x == i组件时,它返回从 11 到 19 的素数。

nums = range(2, 20) 

for i in range(2, 8): 
     nums = filter(lambda x: x % i, nums)

print nums

Again, I don't understand why it ignores all primes below 11.同样,我不明白为什么它会忽略 11 以下的所有素数。

Next, I tried this:接下来,我尝试了这个:

nums = [13] 

for i in range(2, 8): 
     nums = filter(lambda x: x % i, nums)

print nums

Again, this makes no sense to me.同样,这对我来说毫无意义。 The lambda is iterating over x in nums correct? lambda 在nums迭代x是否正确? And i is iterating over the range 2 to 7. So, aren't we taking 13 % i ... for 2 to 7?并且i在 2 到 7 的范围内进行迭代。那么,我们不是将13 % i ... 用于 2 到 7 吗? How does that result in "13"?这如何导致“13”?

Using the same logic as immediately above, I did the same thing with "13", but using x == i in the lambda.使用与上面相同的逻辑,我对“13”做了同样的事情,但在 lambda 中使用了x == i

for i in range(2, 8): 
     nums = filter(lambda x: x == i, nums)

print nums

And as I expected, it returned an empty list -- which makes sense in my mind, because 13 never appears in the range of 2 to 7.正如我所料,它返回了一个空列表——这在我看来是有道理的,因为 13 从未出现在 2 到 7 的范围内。

For reference to anyone trying to help, this is the mindset I'm in when I work with filter() and lambdas:对于任何试图提供帮助的人,这是我在使用filter()和 lambdas 时的心态:

a = range (1, 11)
b = range (9, 20) 

for i in filter(lambda x: x in a, b):
    print i,

This, of course, gives us "9 10".当然,这给了我们“9 10”。 I know the structure of the loop is different, but hopefully it will help you see where my confusion lies.我知道循环的结构是不同的,但希望它可以帮助您了解我的困惑所在。

I have worked with filter() and lambdas somewhat extensively, so I thought I could figure it out, but I'm stumped!我已经广泛地使用filter()和 lambdas,所以我想我可以弄清楚,但我很难过! I just hope the answer isn't so blindingly obvious that I feel like an idiot...我只是希望答案不要太明显以至于我觉得自己像个白痴......

The first code block you posted is the easiest example for me to explain this:您发布的第一个代码块是我解释这一点的最简单示例:

primes = range(2, 20) 
for i in range(2, 8): 
    primes = filter(lambda x: x == i or x % i, primes)
print primes

When using the Sieve of Eratosthenes method, the important thing to note is that you only have to remove numbers that are products of numbers up to the square root of the max .使用埃拉托色尼筛法时,需要注意的重要一点是,您只需删除作为最大平方根的数字的乘积的数字。 The use of range(2,8) above implements this (it goes from 2 to 7, which is further than necessary).上面使用range(2,8)实现了这一点(它从 2 到 7,这超出了必要)。 The square root of 19 (the highest number in the outer range that is checked) is between 4 and 5. So the highest number that should be checked in the range is 4 (we only need to check integers). 19的平方根(被检查的外部范围内的最大数)在4到5之间,所以该范围内应该检查的最大数是4(我们只需要检查整数)。

Using this knowledge, you could improve the code to be as follows (this finds primes <= 19):使用这些知识,您可以将代码改进为如下(这会发现质数 <= 19):

import math
max = 19    #Set it here
max += 1
primes = range(2, max) 
for i in range(2, int( math.ceil(math.sqrt(max)) )): 
    primes = filter(lambda x: x == i or x % i, primes)
print primes

Note that instead of using floor and then adding one because range is exclusive, I use ceil .请注意,我使用ceil ,而不是使用floor然后添加一个,因为range是独占的。

Run it here: http://repl.it/8N8在这里运行: http : //repl.it/8N8

Edit: I also realized this (and the code provided in the question) isn't a complete implementation of the sieve method, since according to the algorithm, we should only flag multiples of primes , meaning that the inner use of range is not as efficient as it should be.编辑:我也意识到这个(以及问题中提供的代码)不是筛法的完整实现,因为根据算法,我们应该只标记素数的倍数,这意味着range的内部使用不是作为应该是高效的。

See a graphical illustration of the algorithm in progress:查看正在进行的算法的图形说明:

埃拉托色尼筛

It looks like a compact (but somewhat obscure) implementation of the Sieve of Eratosthenes [EDIT: as pointed out in the comments, this is in fact an "unfaithful sieve" as the trial division causes worse time complexity than the actual Sieve of Eratosthenes].它看起来像是 Eratosthenes 筛选的紧凑(但有些模糊)实现 [编辑:正如评论中所指出的,这实际上是一个“不忠实的筛选”,因为试验划分导致比实际的 Eratosthenes 筛选更糟糕的时间复杂度] .

The first line is just an arbitrary search range of consecutive integers to filter for primes:第一行只是连续整数的任意搜索范围以过滤素数:

primes = range(2, 20)

Next, following the sieve algorithm , we iterate with integer i in range (2, n) where n is naively the largest number in the search range (though in this case, 7 is the chosen upper bound -- more on this below).接下来,按照筛分算法,我们使用范围 (2, n) 中的整数 i 进行迭代,其中 n 天真地是搜索范围中的最大数(尽管在这种情况下,7 是所选的上限——更多内容见下文)。

for i in range(2, 8): 
    primes = filter(lambda x: x == i or x % i, primes)

The algorithm states that we include i and exclude multiples of i .该算法声明我们包括 i并排除i 的倍数 That's what the lambda predicates filter for --这就是 lambda 谓词过滤器的内容——

  • include i: x == 1包括我: x == 1
  • exclude multiples of i: x % i -- this is short hand for x % i != 0 .排除 i 的倍数: x % i - 这是x % i != 0简写。 In other words, x is not divisible by i, or alternatively, x is not a multiple of i.换句话说,x 不能被 i 整除,或者 x 不是 i 的倍数。

The upper bound of 8 seems somewhat arbitrary -- minimally, we only need to search up to sqrt(n) , since sqrt(n) * sqrt(n) = n means that sqrt(n) is an upper bound on the search space. 8 的上限似乎有些随意——至少,我们只需要搜索到sqrt(n) ,因为sqrt(n) * sqrt(n) = n意味着sqrt(n)是搜索空间的上限.

The square root of 19 is approximately 4.4, and in this example you see that the list of primes does not change after i = 3. 19 的平方根大约是 4.4,在这个例子中你会看到质数列表在 i = 3 后没有改变。

In [18]: primes = range(2, 20)

In [19]: for i in range(2, 8):
   ....:     primes = filter(lambda x: x == i or x % i, primes)
   ....:     print i, primes
   ....:
2 [2, 3, 5, 7, 9, 11, 13, 15, 17, 19]
3 [2, 3, 5, 7, 11, 13, 17, 19]
4 [2, 3, 5, 7, 11, 13, 17, 19]
5 [2, 3, 5, 7, 11, 13, 17, 19]
6 [2, 3, 5, 7, 11, 13, 17, 19]
7 [2, 3, 5, 7, 11, 13, 17, 19]

I have written a simple list comprehension to generate prime numbers.我写了一个简单的列表理解来生成素数。 Of course the core idea was copied in stack overflow.当然,核心思想是在堆栈溢出中复制的。 To be honest it took time for me to understand it as I was beginner in python.老实说,当我是 Python 初学者时,我花了一些时间来理解它。 I have used this list comprehension by calling a lambda function separately.我通过单独调用 lambda 函数来使用此列表推导式。 So first I will discuss the lambda function.所以首先我将讨论 lambda 函数。

lambda function: is_prime = lambda x: all(x % y != 0 for y in range(2,int(math.sqrt(x)) + 1)) lambda 函数: is_prime = lambda x: all(x % y != 0 for y in range(2,int(math.sqrt(x)) + 1))

Now the list comprehension using the above lambda.现在使用上述 lambda 进行列表推导。

primes = [x for x in range(30) if is_prime(x) == True] primes = [x for x in range(30) if is_prime(x) == True]

Try this:尝试这个:

ip_list = [100, 200, 300, 17, 19, 23, 21]

is_prime = list(filter(lambda i: all(i%j!=0 for j in range(2, i//2)), ip_list))

print(is_prime)

这是从 2 - 100 获取素数的代码

Code :

l=list(filter(lambda x: not list(filter(lambda y : x%y==0, range(2,x))),range(2,100)))

I think the answer is fairly simple.我认为答案很简单。 Increase your set of primes from range(2,20) to range(2,30) and try your thought experiment again.将您的质数集从 range(2,20) 增加到 range(2,30),然后再次尝试您的思想实验。 It will me much more obvious.这会让我更加明显。

the filter function will return values for the range of range(2,20) that the filter 函数将返回 range(2,20) 范围内的值

filter(lambda x: x == i or x % i, primes)

returns true.返回真。

In addition to increasing the primes from range(2,20) to range(2,30), play with your inner filter criteria and you will start to see the differences you are looking for.除了将质数从 range(2,20) 增加到 range(2,30) 之外,使用您的内部过滤条件,您将开始看到您正在寻找的差异。

#!/usr/bin/python

primes = range(2, 30) 
for i in range(2, 3): 
    primes = filter(lambda x: x == i or x % i, primes)

print primes

which results in:这导致:

[2, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29]

and

#!/usr/bin/python

primes = range(2, 30) 
for i in range(2, 4): 
    primes = filter(lambda x: x == i or x % i, primes)

print primes

results in结果是

[2, 3, 5, 7, 11, 13, 17, 19, 23, 25, 29]

This code snippet will print prime numbers from 1 to 15:此代码段将打印从 1 到 15 的素数:

lst = filter(lambda x: len(list(filter(lambda n: x % n != 0, range(2, x)))) == x - 2, range(15))
print (list(lst))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM