为什么在这种情况下使用发电机功能的速度是原来的两倍?

时间:2015-06-22 06:59:00

标签: python performance generator

两种实现共同的代码:

from math import sqrt

def factors(x):
    num = 2
    sq = int(sqrt(x))
    for i in range(2, sq):
        if (x % i) == 0:
            num += 2
    return num + ((1 if sq == sqrt(x) else 2) if x % sq == 0 else 0)

1。没有使用生成器函数的实现:

i = 1
while True:
    if factors(i * (i+1) * 0.5) > 500:
        print(int(i * (i+1) * 0.5))
        break
    i += 1

2。使用生成器函数的实现:

def triangle():
    i = 1
    while True:
        yield int(0.5 * i * (i + 1))
        i += 1

t = triangle()

while True:
    num = t.__next__()
    if factors(num) > 500:
        print(num)
        break

问题:

第一个实现大约需要4秒,而第二个大约需要8.2秒。为什么两个实现的运行时间之间有这么大的差异?

4 个答案:

答案 0 :(得分:11)

temp1目录():

def temp1():
        i = 1
        while True:
            if factors(i * (i+1) * 0.5) > 500:
                print(int(i * (i+1) * 0.5))
                break
            i += 1

TEMP2():

def temp2():
    def triangle():
        i = 1
        while True:
            yield int(0.5 * i * (i + 1))
            i += 1

    t = triangle()

    while True:
        num = t.next()
        if factors(num) > 500:
            print(num)
            break

c两者兼得:

enter image description herefactors中的temp1()来电更改为factors(int(...))后,temp1()需要相同的时间

Modified temp1 to pass int rather than float:

def temp1():
    i = 1
    while True:
        if factors(int(i * (i+1) * 0.5)) > 500:
            print(int(i * (i+1) * 0.5))
            break
        i += 1

enter image description here

事实证明,在您的第一个实现中,您将float传递给factors(),并且浮点运算比整数运算复杂

为什么浮点运算很复杂?

因为浮点数的内部表示方式与整数不同,它们用3个部分表示为符号,尾数和指数(IEEE 754),而整数的表示非常简单,整数的加法和减法等操作也是如此在内部使用加法,减法和移位操作的组合来执行乘法和除法。因为整数加法和减法很简单,所以它们的除法/乘法也是如此,因此浮点运算是一些昂贵的

为什么浮点模数比Integer贵?

答案与上面的相同,模运算只不过是上面提到的基本运算的组合如下:

a mod n = a - (n*int(a/n))

由于浮点数的基本运算更昂贵,因此浮点数的模数也是如此

答案 1 :(得分:8)

在明确的情况下,在调用int之前,你没有使用表达式的factors,因此传递的值将是一个浮点数。

在生成器的情况下,你正在屈服int(...),调用factors传递一个整数。

答案 2 :(得分:3)

您可以删除代码的因子(),使 500 更大。

# implementation 1
i = 1
while True:
    if (i * (i + 1) * 0.5) > n: # n=100000
        # print int(i * (i + 1) * 0.5),
        break
    i += 1

%timeit ,与实现2进行比较:

def triangle():
    i = 1
    while True:
        yield i * (i + 1) * 0.5
        i += 1

t = triangle()

while True:
    num = t.next()
    if num > n:
        # print num,
        break

答案 3 :(得分:2)

据我所知,唯一的区别是你在第一个例子中进行了两次计算i * (i+1) * 0.5。这不是一个昂贵的计算,但它可能会产生很大的不同,因为它是该计划的一个重要部分..