我正在研究Project Euler问题12,并提出了以下解决方案:
import math
def main():
num = 0
j = 0
numFactors = 0
while numFactors <= 500:
j += 1
num = num + j #num = sum of numbers from 1 to j
#num = (j *(j+1))//2
numFactors = 0
for n in range(1,int(math.sqrt(num))):
if num % n == 0:
numFactors += 2
print(num)
if __name__ == '__main__':
from timeit import Timer
t = Timer(lambda: main())
print(t.timeit(number=1))
我的问题是关于线num = num + j
对num = (j *(j+1))//2
。
当只使用单个加法时,程序总是比我取消注释下一行并进行乘法、加法和除法慢。
有人能解释为什么单次操作比做3次慢吗?
我实际上没有看到我的机器性能有任何差异。如果乘法真的比加法快,我也会有点惊讶。
我们可以使用dis
模块来从这两个变体中反汇编字节码。在两个变体中,大部分都是相同的,因此任何一个函数的性能都应该相同。这是两个不同的部分(第11行是num = num + j
,第12行是num = (j *(j+1))//2
):
11 43 LOAD_FAST 0 (num)
46 LOAD_FAST 1 (j)
49 BINARY_ADD
50 STORE_FAST 0 (num)
12 43 LOAD_FAST 1 (j)
46 LOAD_FAST 1 (j)
49 LOAD_CONST 3 (1)
52 BINARY_ADD
53 BINARY_MULTIPLY
54 LOAD_CONST 4 (2)
57 BINARY_FLOOR_DIVIDE
58 STORE_FAST 0 (num)
两次拆解都有三次操作。它又来了,只显示了每个变体特有的行:
11 43 LOAD_FAST 0 (num)
12 43 LOAD_FAST 1 (j)
49 LOAD_CONST 3 (1)
53 BINARY_MULTIPLY
54 LOAD_CONST 4 (2)
57 BINARY_FLOOR_DIVIDE
如果乘法真的比加法快,那么我希望精通字节码的人能够解释为什么num
的LOAD_FAST
比第12行的五次运算快。但在我的外行看来,我预计带有更多字节码操作的变体需要更长的时间。