了解埃拉托色尼的筛在Python(Understanding Sieve of Eratosthen

2019-10-18 07:14发布

我发现了一个Python示例代码,让出所有的素数高达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)

如何循环作品的解释,将不胜感激。

编辑- 想通了,代码一切都错了它是指25作为主要通过发现,这不是没有筛网更深入的搜索,可有人告诉它利用筛在python的发电机和解释

Answer 1:

该代码是在使用试除法以产生质数的序列的一种尝试。

要纠正它:

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


Answer 2:

首先,这不是一个筛子。

这是如何工作的。 pp是,我们要测试的数量。 在while循环的每次迭代中,我们去了所有已知的素数( ps ),并检查它们是否分裂pp 。 如果他们中的一个呢, pp不是素,我们移动到下一个数字。 否则,我们添加pp移动之前,以素数的列表。

pp%a==0基本上是说“的remander pp时除以a是零”,即a划分pppp不是素数。

这样继续下去,直到我们正在检查的数量比我们已经设置了一些上限(大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

这是不是最有效的筛子(更高效的做的事情for n in range(2*i, lim, i):行,但它会工作, isPrime[i] IFF将是真正的i是一个素数。



Answer 3:

既然没有人还没有显示出真正的筛子或解释它,我会尝试。

的基本方法是开始在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

下面是一些提示,如何这更多的内存高效版本的作品。 它使用dict来存储只与自身因素(如值)沿最低限度的信息,未来非素数(如钥匙)。 由于每个非黄金在发现dict ,它被去除,下一个非主要关键是加有相同因子值。



Answer 4:

上述实施产生错误的答案。 我做了一些修改代码。

但是,这里的上面的代码是如何工作的。

pp = 2
ps = [pp]

我们知道,第一个素数是2,所以,我们生成仅包含数字列表2

lim = raw_input("Generate prime numbers up to what number? : ")

上述线获取用户,这给我们的素数来生成的上限的输入。

while pp < int(lim):    # 1
      pp += 1           # 2
      primeFlag = True  # 3
      for a in ps:      # 4
          if pp%a==0:
             primeFlag = False
          break
      if primeFlag:     # 5
          ps.append(pp)

该奇数行做以下事情。

  1. 运行一个循环,直到达到上限。
  2. 递增pp 1可变。
  3. 设置这是用于测试,如果数字是首要的标志变量。
  4. for在存储于质数列表循环迭代ps ,并检查当前的数量, pp是这些数字中的任何一个整除,如果是,那么这个数是不是素数和primeFlag设置为False ,我们打出来的内for循环。
  5. 如果数字是没有任何之前的素数整除,那么它必须是一个素数,因此,变量primeFlagTrueif语句追加列表pspp


文章来源: Understanding Sieve of Eratosthenes in Python