当前位置: 首页 > 知识库问答 >
问题:

了解蟒蛇中埃拉托斯特尼的筛子

程俊誉
2023-03-14

我在python中找到了一个示例代码,它给出了直到< code>n的所有素数,但我就是不明白,为什么它会这样做?

我读过维基百科上关于埃拉托色尼筛子的文章,但根本不知道它是如何工作的。

pp = 2
ps = [pp]
lim = raw_input("Generate prime numbers up to what number? : ")
while pp < int(lim):
    pp += 1
    for a in ps:
        if pp%a==0:
            break
        else:
            ps.append(pp)


print set(ps)

请解释一下循环是如何工作的。

EDIT-发现代码都错了,因为它表示25为素数,通过更深入的搜索发现这不是筛子,有人能展示一个利用python中筛子的生成器并解释它吗

共有3个答案

俞涵涤
2023-03-14

该代码是使用试验除法来生成一系列素数的尝试。

要纠正它,请执行以下操作:

pp = 2
ps = [pp]
lim = raw_input("Generate prime numbers up to what number? : ")
while pp < int(lim):
    pp += 1
    for a in ps:
        if pp%a==0:
            break
    else:                # unindent
        ps.append(pp)    #  this

为了使它更有效(事实上,是最佳的)试验部门:

pp = 2
ps = [pp]
lim = raw_input("Generate prime numbers up to what number? : ")
while pp < int(lim):
    pp += 1
    for a in ps:
        if a*a > pp:         # stop
            ps.append(pp)    #  early
            break
        if pp%a==0:
            break
解高昂
2023-03-14

首先,这不是筛子。

这就是它的工作原理。pp 是我们要测试的数字。在 while 循环的每次迭代中,我们遍历所有已知的素数 (ps) 并检查它们是否除以 pp。如果其中一个这样做,pp不是素数,我们移动到下一个数字。否则,我们在继续之前将pp添加到素数列表中。

行< code>pp%a==0基本上是说“< code>pp除以< code>a的余数为零”,即< code>a除以< code>pp,并且< code>pp不是质数。

直到我们检查的数字大于我们设置的上限(lim

[编辑:这是筛子]

isPrime = [True for i in range(lim)]
isPrime[0] = False
isPrime[1] = False

for i in range(lim):
    if isPrime[i]:
        for n in range(2*i, lim, i):
            isPrime[n] = False

这不是最有效的筛选(更有效的是在< code>for n in range(2*i,lim,i):行中做事情),但它将工作,并且< code>isPrime[i]将为真当< code>i是素数时。

昌砚
2023-03-14

由于还没有人展示真正的筛子或解释它,我会尝试。

基本方法是从2开始计数,并消除2*2和所有2的高倍数(即4、6、8…),因为它们都不能是素数。3在第一轮比赛中幸存下来,所以它是最好的,现在我们消除了3*3和所有3的高倍数(即9、12、15…)。4个被淘汰,5个幸存等。每个素数的平方是一种优化,它利用了在前几轮中每个新素数的所有较小倍数都将被淘汰的事实。当您使用此过程计算并消除非素数时,只剩下素数。

这是一个非常简单的版本,注意它没有使用模除或根:

def primes(n): # Sieve of Eratosthenes
    prime, sieve = [], set()
    for q in xrange(2, n+1):
        if q not in sieve:
            prime.append(q)
            sieve.update(range(q*q, n+1, q))
    return prime

>>> primes(100)
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73
79, 83, 89, 97]

上面的简单方法速度惊人,但没有利用素数只能是奇数的事实。

这是一个基于生成器的版本,它比我找到的任何其他版本都快,但在我的机器上达到了n = 10**8的Python内存限制。

def pgen(n): # Fastest Eratosthenes generator
    yield 2
    sieve = set()
    for q in xrange(3, n+1, 2):
        if q not in sieve:
            yield q
            sieve.update(range(q*q, n+1, q+q))

>>> timeit('n in pgen(n)', setup="from __main__ import pgen; n=10**6", number=10)
5.987867565927445

这是一个稍微慢一点但内存效率更高的生成器版本:

def pgen(maxnum): # Sieve of Eratosthenes generator
    yield 2
    np_f = {}
    for q in xrange(3, maxnum+1, 2):
        f = np_f.pop(q, None)
        if f:
            while f != np_f.setdefault(q+f, f):
                q += f
        else:
            yield q
            np = q*q
            if np < maxnum:
                np_f[np] = q+q

>>> timeit('n in pgen(n)', setup="from __main__ import pgen; n=10**6", number=10)
7.420101730225724

>>> list(pgen(10))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47]

要测试一个数字是否为素数,只需执行以下操作:

>>> 539 in pgen(539)
False
>>> 541 in pgen(541)
True

以下是有关此内存效率更高的版本如何工作的一些提示。它使用字典存储最少的信息,即下一个非质数(作为键)及其因子(作为值)。由于在字典中找到每个非素数,因此将其删除,并添加具有相同因子值的下一个非质数键。

 类似资料:
  • 我正在尝试编写一个程序来实现对埃拉托西的筛选。我可以从2到任何给定的结束编号,但我们正在处理的赋值要求我们输入起始值。我完全被卡住了。我试过很多不同的代码,但它总是给我奇怪的答案。 我的起点是起始值,终点是结束值。我基本上想找到这个范围的素数。谢谢!!!

  • 做一个简单的筛子很容易: 但是当N非常大并且我无法在内存中持有这种数组时,该怎么办?我已经查找了分段筛方法,它们似乎涉及查找素数,直到sqrt(N),但我不明白它是如何工作的。如果 N 非常大(比如 10^18)怎么办?

  • 在一个类作业中,我被要求用Java编写Eratostenes筛选代码,我的代码效率非常低。运行时间不长,但我相当肯定,除了像我一样列出所有内容外,还有其他循环的空间。。 这是我的代码: 基本上,我所做的是将所有不是质数的元素设置为true… 所以我的主要2个问题是1。有没有办法实现一个循环,使代码更短2。如何打印此数组中所有为 true(质数)的元素

  • 我在我的一个班级里做的一个作业,我们必须实现一个厄拉多塞的筛子。我已经尝试了七次来得到一个有效的代码,并且尝试了整合我研究过的许多解决方案。我终于有一个可以输出数字的了。不幸的是,它同时打印合数和质数,但不打印2。 我的代码如下: 我怀疑我的循环有问题。我修复了前两个循环的和变量,以便它从2开始打印出来,问题似乎是在我将数组初始化为true后,它没有将合数标记为。 提前感谢你的帮助。

  • 我正在实现一个相当快的质数生成器,我得到了一些不错的结果,在埃拉托斯特尼的筛子上进行了一些优化。特别是,在算法的初步部分,我以这种方式跳过2和3的所有倍数: 这里是一个根据埃拉托色尼筛的布尔数组。我认为这是一种只考虑质数2和3的轮式因式分解,按照模式2、4、2、4递增。. 我想做的是实现一个更大的轮子,也许考虑素数2,3和5。 我已经阅读了很多关于它的文档,但我没有看到任何使用埃拉托斯特尼筛子的实

  • 我正在尝试解决spoj上的Prime Path问题,我正在尝试理解在github上找到的解决方案。解决这个问题的广义逻辑是生成所有四位数素数,并添加一个边,如果我们可以通过更改一个数字从一个素数转到下一个素值。我找到的这个解决方案使用筛子来生成所有素数。与此解决方案中的筛分功能相比,维基上的稀土筛分功能有所不同。只需要帮助了解以下代码中筛分函数的变化: 这里的筛选函数计算是什么?我无法理解为什么作