【问题标题】:Why is my code not working faster after I edited it?为什么我的代码在编辑后不能更快地运行?
【发布时间】:2017-06-28 00:49:25
【问题描述】:

我是计算机科学和编程的新手。我正在参加一个免费的在线编程课程,其中一项作业是编写一个程序来生成第 1000 个素数。

仅供参考,这是在 Python 2.5.4 中

这是我从这个论坛的另一个帖子中复制(并稍作编辑)的原始代码:

def isprime(n):

    if n<2:
        return False
    else:
        for i in range(2,(n/2+1)):
            if n%i==0:
                return False
        else:
            return True

def nthprime(n):
    x=[]
    j=2
    while len(x)<n:
        if (isprime(j)) == True:
            x.append(j)
        j =j+1
    return(x[n-1])

print nthprime(1000)

但是,我认为我可以通过如下重写 isprime(n) 函数来使程序更快:

def isprime(n):# First the primality test
    i=1
    if n<2:
        return False
    if (n!=2 and (n/2*2==n)):
        return False
    if n==3:
        return True
    if n==5:
        return True
    else:
        while i <= (n/2+1):
            i+=2
            if n%i==0:
                return False
        else:
              return True  

这样,当它只检查 n 是否可以被奇数整除时(​​代码中的这一点,我们已经知道 n 是奇数,因此不能被任何偶数整除)。

我认为以这种方式重写它会使程序运行速度提高一倍(因为它只检查一半的数字),但它似乎花费了相同的时间,甚至比原来的时间稍长一些之前服用。

另外,有没有办法重写第二个代码块来摆脱:

if n==3:
    return True
if n==5:
    return True 

我包含它的唯一原因是因为我意识到我的算法会为 3 和 5 生成“假”,即使它们是素数。

【问题讨论】:

  • 你为什么要学习一个九岁的python版本?你应该看看 python 3.6
  • if n in [3,5]: return Trueif n == 3 or n == 5: return True
  • 提示:如果您正在寻找因子对,一个因子将始终是
  • 你应该为你的代码计时。在我的系统上测得,您的新版本速度提高了 42%。
  • n/2*2==n 是检查偶数的一种不好(在 Python 3 中是错误的)方法。

标签: python python-2.5


【解决方案1】:

我明白您的优化目标是什么,但我认为您实现的逻辑并不是您想要的。相反,请考虑其他可以减少必须检查的数字数量的方法。

我推荐的第一个是立即排除偶数:

def isprime(n):
    if n < 2 or n % 2 == 0:
        return False
    # ...

另一个您需要检查的地方比您需要的更多是在优化失败时检查您依赖的因素。不用一路跑到n / 2;你需要担心的最大因素是sqrt(n)(一旦你通过了rootn,你就开始检查你已经检查过的因素,例如,如果你正在检查n = 6,一旦你检查了2,您已经检查过 3)。下面是相应的优化:

def isprime(n):
    # ...
    for i in range(2, int(n ** 0.5) + 1):
        if n % i == 0:
            return False

总之,这是新的isprime(编辑:来自 cmets 的提示):

def isprime(n):
    if n == 2: return True
    if n % 2 == 0: return False

    for i in xrange(3, int(n ** 0.5) + 1, 2):
        if n % i == 0: return False

    return True

计算nthprime(5000),这2个优化花了我的时间从8.497秒到0.108秒。

编辑:demo

【讨论】:

  • int(n ** .5) + 1,实际上,当与 range 一起使用时(在 Python 2.x 上应该是 xrange)。至少检查第 1000 个素数是 7919。
  • @treecoder 我很好奇,math.sqrt() 有什么问题?
  • 您并没有尽可能多地排除n 值。您也可以跳过检查偶数因素。我会做if n == 2: return Trueif n % 2 == 0: return Falsefor i in xrange(3, int(n ** 0.5) + 1, 2): ...
  • @KenY-N math.sqrt(10000) 在我的系统上花费了 286ns。 10000**.5 耗时 23.6ns。 (使用timeit 模块检查)。
  • math.sqrt 本身并没有什么问题,但是当我们可以对某事使用操作符时,使用函数并不会让人觉得惯用。 add(1,1) 没什么问题——但1+1 感觉更好。虽然你可以说math.sqrt 对于不熟悉** 的人来说更易读。
猜你喜欢
  • 2016-12-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-18
  • 1970-01-01
  • 2021-08-11
相关资源
最近更新 更多