【问题标题】:Sieve of Eratosthenes without multiples of 2 and 3没有 2 和 3 倍数的 Eratosthenes 筛
【发布时间】:2019-02-13 23:44:52
【问题描述】:

我正在尝试实现本文Faster Sieve of Eratosthenes 中描述的算法。我很理解这个想法,但我无法理解它究竟是如何通过 python 代码实现的。

经过一番努力,我找到了一种将筛子中的索引转换为数字本身的方法:

number = lambda i: 3 * (i + 2) - 1 - (i + 2) % 2

但主要的问题是我在获得最佳状态后必须做的跳跃。文章解释为:

6np ± p,其中 p 是质数,n - 某个自然数。

对于这种想法,有没有办法使用最后找到的素数的索引来描述跳跃?

提前致谢。

附: 有implementation in Objective-C 我对编程很陌生,只能理解python和js代码。

【问题讨论】:

  • 你可以在他的 GitHub 网站上找到 Objective C 的源代码。
  • 感谢您的回答!我是个新手,只能看懂python和js代码,可惜……
  • 如果你懂JS,我想你会懂C代码,它们非常相似。
  • @Barmar 你是对的。一段时间后,我决定试一试并检查给定的解决方案。这里有一些冗余代码,但我很快就得到了工作 python 解决方案。经过一些重构后,我将在此处发布。谢谢!

标签: python math primes sieve-of-eratosthenes sieve


【解决方案1】:

如果您了解 numpy 以及 Python,请查看 primesfrom2to 的这个实现,取自 this answer in StackOverflow

def primesfrom2to(n):
    # https://stackoverflow.com/questions/2068372/fastest-way-to-list-all-primes-below-n-in-python/3035188#3035188
    """ Input n>=6, Returns a array of primes, 2 <= p < n """
    sieve = np.ones(n/3 + (n%6==2), dtype=np.bool)
    sieve[0] = False
    for i in xrange(int(n**0.5)/3+1):
        if sieve[i]:
            k=3*i+1|1
            sieve[      ((k*k)/3)      ::2*k] = False
            sieve[(k*k+4*k-2*k*(i&1))/3::2*k] = False
    return np.r_[2,3,((3*np.nonzero(sieve)[0]+1)|1)]

在我链接到的那个答案中,这个例程在构建素数列表方面是最快的。我在自己的代码中使用了它的一个变体来探索素数。详细解释这一点需要很多篇幅,但它构建了一个 sieve,它忽略了 2 和 3 的倍数。只有两行代码(以 sieve[ 和以 = False 结尾的代码)标记了新的倍数-找到素数。我认为这就是您所说的“跳跃……在获得最佳状态后”。代码很棘手,但正在学习中。该代码适用于 Python 2,旧版 Python。

这是我自己的一些具有更多 cmets 的 Python 3 代码。可以拿来做对比。

def primesieve3rd(n):
    """Return 'a third of a prime sieve' for values less than n that
    are in the form 6k-1 or 6k+1.

    RETURN: A numpy boolean array. A True value means the associated
            number is prime; False means 1 or composite.

    NOTES:  1.  If j is in that form then the index for its primality
                test is j // 3.
            2.  The numbers 2 and 3 are not handled in the sieve.
            3.  This code is based on primesfrom2to in
                <https://stackoverflow.com/questions/2068372/
                fastest-way-to-list-all-primes-below-n-in-python/
                3035188#3035188>
    """
    if n <= 1:  # values returning an empty array
        return np.ones(0, dtype=np.bool_)
    sieve = np.ones(n // 3 + (n % 6 == 2), dtype=np.bool_)  # all True
    sieve[0] = False   # note 1 is not prime
    for i in range(1, (math.ceil(math.sqrt(n)) + 1) // 3): # sometimes large
        if sieve[i]:
            k = 3 * i + 1 | 1  # the associated number for this cell
            # Mark some of the stored multiples of the number as composite
            sieve[k * k                 // 3 :: 2 * k] = False
            # Mark the remaining stored multiples (k times next possible prime)
            sieve[k * (k + 4 - 2*(i&1)) // 3 :: 2 * k] = False
    return sieve

def primesfrom2to(n, sieve=None):
    """Return an array of prime numbers less than n.

    RETURN: A numpty int64 (indices type) array.

    NOTES:  1.  This code is based on primesfrom2to in
                <https://stackoverflow.com/questions/2068372/
                fastest-way-to-list-all-primes-below-n-in-python/
                3035188#3035188>
    """
    if n <= 5:
        return np.array([2, 3], dtype=np.intp)[:max(n - 2, 0)]
    if sieve is None:
        sieve = primesieve3rd(n)
    elif n >= 3 * len(sieve) + 1 | 1:  # the next number to note in the sieve
        raise ValueError('Number out of range of the sieve in '
                         'primesfrom2to')
    return np.r_[2, 3, 3 * np.nonzero(sieve)[0] + 1 | 1]

这里有什么不懂的可以问我。

【讨论】:

  • 非常感谢!我需要一些时间来使用这段代码:) 我真的很想了解这个非 2;3 的倍数的想法的实现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-05
  • 1970-01-01
  • 1970-01-01
  • 2013-05-28
  • 2015-09-06
相关资源
最近更新 更多