Python 中的埃拉托色尼惰性筛法

发布于 2024-11-24 17:36:12 字数 922 浏览 1 评论 0原文

我正在尝试用 Python 3.2 编写一个惰性版本的埃拉托斯特尼筛法。代码如下:

import itertools
def primes():
    candidates = itertools.count(2)
    while True:
        prime = next(candidates)
        candidates = (i for i in candidates if i % prime)
        yield prime

但是,当我迭代 primes() 时,我只得到连续的数字。例如,

print(list(itertools.islice(primes(),0,10)))

打印列表

[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

令我惊讶的是,对 primes() 进行以下微小修改使其工作:

def primes():
    candidates = itertools.count(2)
    while True:
        prime = next(candidates)
        candidates = (i for i in candidates if i % prime)
        next(itertools.tee(candidates)[1]) ########### NEW LINE
        yield prime

我猜我错过了有关生成器参数范围的一些内容

candidates = (i for i in candidates if i % prime)

,但我无法看到如何在不添加此随机数的情况下修复代码- 寻找新的线路。有人知道我做错了什么吗?谢谢。

I am trying to code a lazy version of Sieve of Eratosthenes in Python 3.2. Here's the code:

import itertools
def primes():
    candidates = itertools.count(2)
    while True:
        prime = next(candidates)
        candidates = (i for i in candidates if i % prime)
        yield prime

However, when I iterate over primes(), I only get consecutive numbers. E.g.,

print(list(itertools.islice(primes(),0,10)))

prints the list

[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

To my surprise, the following tiny modification of primes() makes it work:

def primes():
    candidates = itertools.count(2)
    while True:
        prime = next(candidates)
        candidates = (i for i in candidates if i % prime)
        next(itertools.tee(candidates)[1]) ########### NEW LINE
        yield prime

I am guessing I am missing something about the scope of the parameters of the generator

candidates = (i for i in candidates if i % prime)

but I cannot see how to fix the code without adding this random-looking new line. Does anybody know what I am doing wrong? Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

坏尐絯℡ 2024-12-01 17:36:12

修复实际上是将: 替换

candidates = (i for i in candidates if i % prime)

为:

candidates = (lambda prime: (i for i in candidates if i % prime))(prime)

the fix is really to replace:

candidates = (i for i in candidates if i % prime)

with:

candidates = (lambda prime: (i for i in candidates if i % prime))(prime)
清引 2024-12-01 17:36:12

如果您担心变量的范围,请创建对象/函数来为您保留这些变量:(

def filter_multiples(n, xs):
    for i in xs:
        if i % n
            yield i

def primes():
    candidates = itertools.count(2)
    while True:
        prime = next(candidates)
        candidates = filter_multiples(prime, candidates)
        yield prime

我现在无法访问 Pytho 解释器,所以我不知道这最终是否真的有效,或者不是...)


顺便说一句,您使用的算法并不是真正的埃拉斯托尼筛法。如果您有时间,请查看这篇很酷的论文:http:// /www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf

If you are worried about the scope of the variables, create objects/functions to keep these variables for you:

def filter_multiples(n, xs):
    for i in xs:
        if i % n
            yield i

def primes():
    candidates = itertools.count(2)
    while True:
        prime = next(candidates)
        candidates = filter_multiples(prime, candidates)
        yield prime

(I don't have access to a Pytho interpreter right now, so I don't konw if this actually works in the end or not...)


BTW, the algorithm you use is not really the sieve of Erastothenes. Take a look in this cool paper if you have some time: http://www.cs.hmc.edu/~oneill/papers/Sieve-JFP.pdf

偏闹i 2024-12-01 17:36:12

下面是基于论文中的 haskell 代码的真正素数筛的 Python 实现: The Genuine Sieve of Eratosthenes by Melissa E. O'Neill

它不使用递归或试除法,但相当消耗内存。

from heapq import heappush, heappop, heapreplace
def sieve():
    w = [2,4,2,4,6,2,6,4,2,4,6,6,2,6,4,2,6,4,6,8,4,2,4,2,4,8,6,4,6,2,4,6,2,6,6,4,2,4,6,2,6,4,2,4,2,10,2,10]
    for p in [2,3,5,7]: yield p
    n,o = 11,0
    t = []
    l = len(w)
    p = n
    heappush(t, (p*p,n,o,p))
    yield p
    while True:
        n,o = n+w[o],(o+1)%l
        p = n
        if not t[0][0] <= p:
            heappush(t, (p*p,n,o,p))
            yield p
            continue
        while t[0][0] <= p:
            _,b,c,d = t[0]
            heapreplace(t, (b*d,b+w[c],(c+1)%l,d))

打印内容如下

import itertools
print list(itertools.islice(sieve(),0,10))

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

Here is a Python implementation of the genuine prime sieve based on the haskell code in the paper: The Genuine Sieve of Eratosthenes by Melissa E. O'Neill

It does not use recursion or trial division but is rather memory hungry.

from heapq import heappush, heappop, heapreplace
def sieve():
    w = [2,4,2,4,6,2,6,4,2,4,6,6,2,6,4,2,6,4,6,8,4,2,4,2,4,8,6,4,6,2,4,6,2,6,6,4,2,4,6,2,6,4,2,4,2,10,2,10]
    for p in [2,3,5,7]: yield p
    n,o = 11,0
    t = []
    l = len(w)
    p = n
    heappush(t, (p*p,n,o,p))
    yield p
    while True:
        n,o = n+w[o],(o+1)%l
        p = n
        if not t[0][0] <= p:
            heappush(t, (p*p,n,o,p))
            yield p
            continue
        while t[0][0] <= p:
            _,b,c,d = t[0]
            heapreplace(t, (b*d,b+w[c],(c+1)%l,d))

The following:

import itertools
print list(itertools.islice(sieve(),0,10))

prints:

[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文