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

Python中Eratosthenes的高效筛选

费学
2023-03-14

#Python中的这段非常简短的代码试图模拟前N个自然数的“Eratosthennes筛”,并限制(0)脚本长度;(1) 最小化“if语句”和“for/while循环”;(2) CPU时间方面的效率。

import numpy as np
N = 10**5
a = np.array(range(3,N,2))
for j in range(0, int(round(np.sqrt(N),0))):
    a[(a!=a[j]) & (a%a[j] == 0)] = 0
    a = a[a!=0]
a = [2]+list(a)

在Intel Core I5上,它返回第一个数字中的质数:

    < Li > 0.03秒内N = 100,000; < Li > 0.63秒内N = 1,000,000; < li>N = 10,000,000在22.2秒内。

有人想在上述限制内分享更高效的CPU时间代码吗?

共有3个答案

商正浩
2023-03-14

10.000.000为1.94秒

def sieve_eratosthene(limit):

    primes = [True] * (limit+1)
    iter = 0

    while iter < limit**0.5 :
        if iter < 2:
            primes[iter]= False

        elif primes[iter]:
            for i in range(iter*2, limit+1, iter):
                primes[i] = False

        iter+=1

    return(x for x in range(limit+1) if primes[x])
管梓
2023-03-14

我决定玩这个,并创建了一个进一步优化的NumPy版本,由@user2357112发布,支持Monica,它使用Numba JIT来加快速度。

import numba
import numpy
import timeit
import datetime 

@numba.jit(nopython = True, parallel = True, fastmath = True, forceobj = False)
def sieve (n: int) -> numpy.ndarray:
    primes = numpy.full(n, True)
    primes[0], primes[1] = False, False
    for i in numba.prange(2, int(numpy.sqrt(n) + 1)):
        if primes[i]:
            primes[i*i::i] = False
    return numpy.flatnonzero(primes)

if __name__ == "__main__":
    
    timestart = timeit.default_timer()
    print(sieve(1000000000))
    timestop = timeit.default_timer()
    timedelta = (timestop - timestart)
    print(f"Time Elapsed: {datetime.timedelta(seconds = timedelta)}")

else:
    pass

在我的笔记本电脑上,我筛选出0:00:10.378686秒内第一个10亿(1e9)自然数中的素数。JIT在这里提供了至少一个数量级的性能;在撰写本文时,下一个最快的答案需要0:01:27.059963分钟。遗憾的是,我在这个系统(苹果)上没有英伟达图形处理器和库达,否则我会用它。

陆晓博
2023-03-14

一个实际的厄拉多塞数字筛看起来像这样:

def sieve(n):
    flags = numpy.ones(n, dtype=bool)
    flags[0] = flags[1] = False
    for i in range(2, n):
        # We could use a lower upper bound for this loop, but I don't want to bother with
        # getting the rounding right on the sqrt handling.
        if flags[i]:
            flags[i*i::i] = False
    return numpy.flatnonzero(flags)

它维护一个“可能素数”标志的数组,并直接取消设置对应于素数倍数的标志,而无需测试可除性,特别是对于当前正在处理的素数不可整除的数字。

我们所做的是试除法,在这里,我们只需要通过并测试数字是否可以被候选除数整除。即使是一个好的试除法实现也需要做更多的操作和更昂贵的操作,而不是筛子。你的实现做的工作甚至更多,因为它考虑了非质数候选除数,并且因为它一直在对它应该知道是质数的数字进行可整除性测试。

 类似资料:
  • 我正在尝试在Java中创建一个快速的素数生成器。人们(或多或少)认为,最快的方法是埃拉托斯特尼的分段筛:https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes。可以进一步实施许多优化以使其更快。截至目前,我的实现在大约秒内生成低于的素数,但我希望让它更快,至少打破秒的障碍。为了增加获得良好回复的机会,我将包括算法和代码的演练。 尽管如此,作为 ,我希

  • null null 谢谢你的帮助!

  • 问题内容: 我已经可以存储所有32位质数,并且 我想用它们来生成一些64位质数 。即使对逻辑和编译进行了优化,使用试验划分也太慢了。 我正在尝试修改Eratosthenes的筛网以使用预定义列表,如下所示: 在数组A中从2到4294967291 在数组B中从2 ^ 32到X inc减1 找到C,它是当前素数的第一个倍数。 从C标记开始并以当前素数跳至X。 转到1。 问题是使用模数查找素数的第3步,

  • 问题内容: 我想为正在构建的数学应用程序找到质数,并遇到了Eratosthenes方法的Sieve。 我已经用Python编写了一个实现。但这太慢了。可以说,如果我想找到所有小于200万的素数。这需要> 20分钟。(我此时已停止)。我怎样才能加快速度? 更新: 我最终对这段代码进行了分析,发现花了很多时间从列表中删除一个元素。考虑到它必须遍历整个列表(最坏的情况)以找到元素,然后删除它,然后重新调

  • 为了澄清,这与Eratosthenes的问题Sieve-Finding Primes Python不同,因为我不想在两个数字之间生成素数,但我想检查一个数字是否是素数。 我做了下面的代码来确定一个数字是否是素数。然后我听说了埃拉托色尼算法的筛子,它显然更快,但我不知道如何在下面的代码中编写它? 你们能帮帮我吗?

  • 问题内容: 当我们必须处理10k量纲的向量时,python的外部乘积似乎很慢。有人可以告诉我如何在python中加快此操作的速度吗? 代码如下: 由于我必须多次执行此操作,因此我的代码越来越慢。 问题答案: 确实没有比这更快的速度,这些是您的选择: numpy.outer numpy.einsum 麻巴 Parakeet 赛顿 茶野 py 结论: