这里有两个功能完全相同(将数字的阶乘相加)。 数组F包含0!... 9!
N = 1_000_000
F = [1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880]
def facdigits1(n):
total = 0
for i in map(int, str(n)):
total += F[i]
return total
def facdigits2(n):
return sum((F[i] for i in map(int, str(n))))
total = 0
for i in range(2, N):
n = facdigits1(i)
total += n
print(total)
完全出乎意料的(对我而言),facdigits2比facdigits1慢了约20%。我预料相反。知道这里发生了什么吗?
答案 0 :(得分:2)
设置开销似乎更高。这是2**25 / n
次用三种方法求和[1] * n
的时间(以秒为单位)(因此,每n个行,因此每一行,求和的总数相同,即2**25
)。请注意,这三者的启动速度都很慢,而循环的启动速度最快。不知道为什么循环在低于2.0之后上升到2.8(编辑:也许Python's small integers cache使得总和低于257的速度更快,但是其他两个解决方案似乎并没有因此受到影响)。
n loop generator pure
-----------------------------------
1 11.3239 24.6003 12.5587
2 6.8343 13.6080 5.6892
4 4.4053 7.9283 3.0991
8 3.2007 5.5467 1.8115
16 2.5485 3.7965 1.1166
32 2.2361 3.0682 0.7247
64 2.0101 3.0527 0.5513
128 2.0220 2.4149 0.4475
256 1.8081 2.3848 0.3966
512 2.0703 2.3418 0.4229
1024 2.2276 2.2966 0.3706
2048 2.2751 2.2856 0.3614
4096 2.2761 2.3269 0.3533
8192 2.3085 2.3623 0.3671
16384 2.3395 2.2970 0.3552
32768 2.4804 2.3583 0.4097
65536 2.5998 2.3151 0.3572
131072 2.7952 2.2654 0.3954
262144 2.7445 2.4830 0.3599
524288 2.7740 2.3462 0.3565
1048576 2.7449 2.2845 0.3592
2097152 2.8187 2.2246 0.3708
4194304 2.8307 2.2691 0.3572
8388608 2.8036 2.2731 0.3690
16777216 2.7704 2.3388 0.3649
33554432 2.8328 2.3018 0.3545
您的n≤6,因此我的测试同意发电机的速度较慢。就我而言,这是更极端的情况,大概是因为我没有做任何其他事情,例如将数字转换为字符串,查找列表索引以及对大数字求和。
代码:
from timeit import timeit
def sum_loop(numbers):
total = 0
for number in numbers:
total += number
return total
def sum_generator(numbers):
return sum(number for number in numbers)
def sum_pure(numbers):
return sum(numbers)
emax = 25
for e in range(emax + 1):
n = 2**e
number = 2**(emax - e)
numbers = [1] * n
print('%8d' % n, end='')
for f in sum_loop, sum_generator, sum_pure:
t = timeit(lambda: f(numbers), number=number)
print(' %7.4f' % t, end='')
print()
答案 1 :(得分:1)
问题本身隐藏在sum
函数相对于生成器的性能降低中。总结一些答案,我得出的结论是,生成器不会一次将所有元素存储在内存中。这是我定义求和的方法:
def s1(size):
total = 0
for i in range(size):
total += i
return total
def s2(size):
return sum(i for i in range(size))
def s3(size):
return sum(range(size))
def s4(size):
def gen(size):
for i in range(size):
yield i
return sum(gen(size))
def s5(size):
def gen(size):
i=0
while i<size:
yield i
i+=1
return sum(gen(size))
from time import time
import numpy as np
time_avg=[]
size = 10000000
for i in range(10):
times=[]
for s in [s1,s2,s3,s4,s5]:
t = time()
s(size)
times.append(round(time()-t, 3))
time_avg.append(times)
print(np.sum(np.array(time_avg), axis=0)/len(time_avg))
s1
,s2
,s3
,s4
,s5
的时间是:
[0.9624 1.3263 0.6373 1.2426 1.8455]