【问题标题】:How does a Sieve of Eratosthenes work in this code?Eratosthenes 的筛子如何在此代码中工作?
【发布时间】:2021-12-28 04:02:27
【问题描述】:

我需要一些帮助来解释下面的埃拉托色尼筛。我从其他一些 Stackoverflow 页面复制了它,但我没有逐行理解它。有人可以解释一下吗?

def eratosthenes(n):
    multiples = []
    for i in range(2, n):
        if i not in multiples: 
            print (i)
            for j in range(i*i, n, i):  #Troubled Part
                multiples.append(j)

eratosthenes(100)

我特别没有得到 range(i*i...) 部分。为什么一组括号中有三个属性?另外,为什么我是平方的?谢谢!

【问题讨论】:

  • 范围可以有多个参数。使用 range(a,b,c),您正在执行 range(a,b) 但按 c 计数
  • 这可能是我见过的 Eratosthenes 实现中最糟糕的筛子。可能不是学习的好例子。
  • 我记得有一篇长文章争论说,如果埃拉托色尼筛的实现比二次复杂度还差,那么它就不应该被称为埃拉托色尼筛。

标签: python loops math numbers


【解决方案1】:

让我们逐行进行:

multiples = [] 制作一个合数列表,我们稍后会在这里添加

for i in range (2,n) 我们从 2 循环到 n,试图得到所有的素数。

if i not in multiples 我们正在检查i 是否是我们已经找到的合数

print(i)i一定是素数,所以打印出来

for j in range(i*i,n,i)is 计数,从i*in,因为每个数字都是一个合数。请注意,我们从 i*i 开始,因为像 i*[number<i] 这样的数字将在以前的迭代中记录

multiples.append(j)j 添加到合数列表中

【讨论】:

    【解决方案2】:

    范围中的第三个属性只是一个增量。它是说将 i 添加到 i*i 直到我们到达 n。

    因此,埃拉托色尼筛法的工作原理是在我们前进的过程中去除素数的倍数(即复合数,在倍数列表中跟踪),例如 [2,4,6,8,...],[ 3,9,12,...],[5,25,30,...] 我们继续。

    在上述每个序列的第一个中,我们有素数,序列中的后续元素被添加到倍数列表中

    您突出显示的部分:

    for j in range(i*i, n, i):  #Troubled Part
                    multiples.append(j)
    

    这只是将所有素数的复合倍数相加。更明确地说,让我们看一下 2。

    2 不是倍数。所以打印出来了。那么让我们具体想想接下来会发生什么:

    for j in range(2*2, 100, 2)

    这会将 4、6、8、10 等添加到倍数列表中,这些是我们忽略的数字,因为它们是复合数。您可以将 i*i 简单地视为我们开始的倍数序列中的下一个元素。

    这样,我们继续3,从9、12、15开始,以此类推。

    请注意,在第一次迭代中已经排除了合数 4、6、8,因此我们可以从 9 开始并继续。

    这其实是傅瑞恩指出的重要一点。

    所以用最清晰的术语来说:

    • 2 已打印。多重列表更新为所有其他偶数 [4,6,8,10,...]
    • 接下来我们转到 3,因为它不是倍数。我们将 [9,12,15,18,21,...] 添加到列表中。
    • 请注意,我们无需费心将 6 添加到列表中,因为在我们考虑 2 时它已经在之前添加了。这就是我们不需要执行类似操作的原因
    for j in range(i*2, n, i)
    
    • 过程继续,我们得到的下一个数字是 5,所以 [25,30,35,40,...] 被添加到倍数中

    最终只打印素数。

    【讨论】:

      【解决方案3】:

      multiples 存储素数的所有倍数,例如 2 是素数,然后4,6,8,10,12... 是素数的倍数而不是素数,因此无需检查这些不,因为它们是素数或不是素数他们不是。

      if i not in multiple 表示i 是质数,然后我们保存所有i 的倍数。在您的解决方案中,我认为没有必要在for j in range(i*i, n , i) 中使用i*i,但2*i 将是正确的选择,即for j in range(2*i, n, i)multiples 应该是set 类型而不是list,因为这将允许重复搜索时间复杂度在列表情况下为O(N),在设置情况下为O(1)

      def eratosthenes(n):
          multiples = set()
          for i in range(2, n):
              if i not in multiples: 
                  print (i)
                  for j in range(2*i, n, i):  #Troubled Part
                      multiples.add(j)
      
      eratosthenes(100)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-13
        • 1970-01-01
        • 2019-04-14
        • 2016-04-08
        相关资源
        最近更新 更多