为什么' IF'使得此代码的速度提高了2倍,因为输出相同,并且“如果' IF'额外检查?

时间:2017-05-16 17:48:00

标签: python performance python-3.x

我正在研究这个快速的Eratosthenes发电机筛子,只是想知道为什么,如果检查'每个项目索引,代码运行速度比没有这个检查。谁会想到这个!?这是一般的使用技巧吗?

import time    

def first(n):
    s=time.time()
    full_range = list(range(n))
    zeroes = [0] * n
    '''multiply n until sqrt(n)'''
    for r in range(2, int(n**.5) + 1):
        if full_range[r]:  ##HERE##
            full_range[2 * r:n:r] = zeroes[2 * r:n:r]   
    return list(filter(None, full_range)), print (time.time()-s)


def second(n):
    s=time.time()
    full_range = list(range(n))
    zeroes = [0] * n
    '''multiply n until sqrt(n)'''
    for r in range(2, int(n**.5) + 1):
        #if full_range[r]:   ##HERE##
        full_range[2 * r:n:r] = zeroes[2 * r:n:r]
    return list(filter(None, full_range)), print (time.time()-s)

print(first(100000) == second(100000))

First  0.3749978542327881 seconds
Second 0.9687492847442627 seconds
True

2 个答案:

答案 0 :(得分:0)

用语言来说,你正在做的过程说"将这个数字的所有倍数标记为零。" if语句表示"仅当当前号码为素数时才执行下一步。"

对于筛子中的每个数字,第二个筛子必须将所有2的倍数,然后是3,然后是4,......第一个只将多个素数归零:2,然后是3,然后......

当它达到4时,它看到4已经归零。任何4的倍数是2的倍数,因此它们已经归零。再次标记它们是浪费的工作。

现在我们做5,跳过6,做7,跳过8,9和10 ......

当我们只为主要的除数做这项工作时,我们节省了大量的工作。

答案 1 :(得分:0)

以此为例,说明为什么加速发生在这里:

def first(n):
    s=time.time()
    a = []
    for r in range(n):
        a += [r]
        if r%2:
            for i in range(r):
                a[i] = i
    return a, print (time.time()-s)

def second(n):
    s=time.time()
    a = []
    for r in range(n):
        a += [r]
        for i in range(r):
            a[i] = i
    return a, print (time.time()-s)

>>> first(10000) == second(10000)
1.7188639640808105
3.406471014022827
True

通过添加if语句,您可以摆脱最终不会影响代码结果的循环。通过不运行此循环(在您的情况下是扩展切片),您的程序可以在问题上花费更多时间,而不是花时间做一些对最终结果没有影响的事情。

修改 有趣的是,在运行您提供的代码时,我的时间非常相似,以至于您使用的代码并不重要(有时第一个比第二个慢):

>>> print(first(100000) == second(100000))
0.015606880187988281
0.015592098236083984

>>> print(first(100000) == second(100000))
0.015619993209838867
0.015625953674316406

>>> print(first(100000) == second(100000))
0.0
0.015592098236083984

>>> print(first(100000) == second(100000)) #something wrong with this one
0.0
0.03125309944152832

>>> print(first(100000) == second(100000))
0.0
0.0