Python 3.x 如何提高python程序的速度?

Python 3.x 如何提高python程序的速度?,python-3.x,Python 3.x,我试图用Python 3.4.1编写一个程序,以获得从2到100000的素数 我的问题是,处理所有的信息花费了太多的时间,而且从来没有给我任何结果 我把它放了大约半个小时,它让我的电脑慢了下来,也不能给我想要的东西 我用的是埃拉托什尼的筛子算法 这是我的密码: from math import * def primos(num): num2 = num + 1 tnumeros = [] # tnumeros = every

我试图用Python 3.4.1编写一个程序,以获得从2到100000的素数

我的问题是,处理所有的信息花费了太多的时间,而且从来没有给我任何结果

我把它放了大约半个小时,它让我的电脑慢了下来,也不能给我想要的东西

我用的是埃拉托什尼的筛子算法

这是我的密码:

from math import *

def primos(num):
    num2     = num + 1
    tnumeros = []                      # tnumeros  = every number from 2 to num
    npnumeros= []                      # npnumeros = every number that is no prime
    pnumeros = []                      # pnumeros  = every prime number

    for a in range( 2, num2 ):
        tnumeros.append( a )

    for i in range( 2, int( sqrt( num ) ) + 1 ):
        for j in range( i, int( num / i ) + 1 ):
            np = i * j
            npnumeros.append( np )

    npnumeros = list( set( npnumeros ) )

    for e in tnumeros:
        if ( e in npnumeros ):
            continue
        else:
            pnumeros.append( e )

    return ( str( "".join( str( pnumeros ) ) ) )

print( primos( 100000 ) )

不要为您的
npnumeros
值使用列表;用一套来代替。您只对查找该集合中是否有数字感兴趣,因此从一开始就将其设置为一组:

npnumeros = set()
# ...
for i in range( 2, int( sqrt( num ) ) + 1 ):
    for j in range( i, int( num / i ) + 1 ):
        np = i * j
        npnumeros.add( np )

# npnumeros = list( set( npnumeros ) )  # Remove this line, it's no longer needed

for e in tnumeros:
    if ( e in npnumeros ):
        continue
    else:
        pnumeros.append( e )
代码运行缓慢的原因是在列表中查找数字是O(N)时间,而在O(N)循环中查找数字是O(N^2)时间。但是在一个集合中查找数字是O(1)时间,所以在该循环中有O(N)时间。从O(N^2)到O(N)将代表处理速度上的巨大差异


如果您不理解我使用的O(N)符号,请阅读更多有关它的信息。

这是一个严重截断的答案,因为这个问题可能应该移至CR

一个快速的加速就是将NPNumero作为一个集合而不是一个列表。这意味着后面的计算
if(npnumeros中的e):
将显著加快

修改后的代码:

from math import *

def primos(num):
    num2     = num + 1
    tnumeros = []                      # tnumeros  = every number from 2 to num
    npnumeros= []                      # npnumeros = every number that is no prime
    pnumeros = []                      # pnumeros  = every prime number

    for a in range( 2, num2 ):
        tnumeros.append( a )

    for i in range( 2, int( sqrt( num ) ) + 1 ):
        for j in range( i, int( num / i ) + 1 ):
            np = i * j
            npnumeros.append( np )

    npnumeros = set( npnumeros )

    for e in tnumeros:
        if ( e in npnumeros ):
            continue
        else:
            pnumeros.append( e )

    return ( str( "".join( str( pnumeros ) ) ) )

print( primos( 100000 ) )

运行速度提高约60倍。

这个问题似乎与主题无关,因为它没有bug。可以要求对代码进行检查。或者,你可以说它有一个性能缺陷,因此不符合其规范?这并不是真正的埃拉托斯坦筛:该算法识别素数并同时删除每个连续素数的倍数。在这里,您删除的是每个整数的倍数,而不仅仅是素数的倍数。@matsjoyce:难道您不知道,“运行缓慢”不是一个bug,而是一个特性@琼瓦雷:我看到了埃拉托什尼筛的错误实现。它不是没有bug的。谢谢你,我不明白你说的关于O(N)和这些东西,但是你说的对,把npnumeros作为一个集合而不是一个列表,我的程序会运行得更快。它需要一点时间,但现在可以运行了。@cotuex-基本上,大O表示法是一种表示“这个程序需要多长时间取决于它的输入数据有多大”的方式。O(N)表示“程序的运行时间与输入数据中的项数N成正比”。O(N^2)表示运行时间与N的平方成正比。因此,如果一个O(N)程序需要2秒才能使用2个输入运行,那么使用7个输入运行需要7秒,使用25个输入运行需要25秒。如果一个O(N^2)程序用2个输入运行需要4秒,用7个输入运行需要49秒,用25个输入运行需要625秒(10分钟)。现在:在列表中查找项目是一个O(N)操作,因为Python在列表中循环,一次比较列表中的每个项目。这需要的时间量与N成正比,N是列表中的项目数。如果你在一个大约有N个项目的循环中运行这个调用,那么所花费的时间与N*N或N的平方成正比。这很糟糕:在这种情况下,你的N相当大,大约100000,所以N^2很大。从“与N平方成比例”到“与N平方成比例”的运行时间有很大的不同。Python集合的特点是,在集合中查找一个项需要恒定的时间(用大O表示法写成O(1))。无论集合中只有几个项目,还是有100000个项目,查找“集合中是否包含此项目?”将花费相同的时间。在循环中这样做需要与N*1成比例的时间,而不是NN。因此,当N=100000时,循环仅以100000个时间单位运行(其中一个“时间单位”可能是几微秒),而不是100000^2=100*10亿个时间单位。你的解释非常完美,现在我明白了你对O(N)的意思。谢谢你,谢谢你。您所说的是rmunn所说的,您是对的,但请下次在编写代码时重新检查,因为当您编写代码时,我不知道它是代码还是简单的文本,而且因为我知道它是我的代码,所以我无法完美地将我的旧代码与您的代码进行比较。不过还是谢谢你。