加速Python中的求和

时间:2017-11-07 09:43:40

标签: python python-3.x sum

我在n1中有一个包含数字listn1的大型列表。如果被乘数不在另一个列表中listn2(具有特定特征的素数)且产品低于最大max_n,我想添加每个数字的所有倍数。被乘数在大多数情况下低于10,但最高可达100,000。到目前为止我的代码看起来像:

s = 0
for n1 in listn1:
    s += sum(n1 * i for i in range(1, 1 + max_n // n1) if i not in listn2)

问题:这种方法很懒散。计算listn1listn2需要几秒钟,因此我知道要添加的数字超过一百万。但我昨天晚上开始总结,今天早上还在运行。

是否有一种Pythonic方法来加速这个求和?

2 个答案:

答案 0 :(得分:1)

我有2条建议。

首先,您在每次迭代时都不会与i相乘n1。你可以替换

s += sum(n1 * i for i in range(1, 1 + max_n // n1) if i not in listn2)

s += n1 * sum(i for i in range(1, 1 + max_n // n1) if i not in listn2)

他们完全相同。

其次,没有if i not in listn2条件,您只需简单求和:

sum(i for i in range(1, 1 + max_n // n1)

这与sum([1, 2, 3, 4, 5, 6, 7, 8, ..., (max_n // n1)])相同,等于(max_n // n1) * (1 + max_n // n1) / 2。举一个简单的例子,看看this

要处理if i not in listn2条件,如果listn2较小,则可以加listn2而不是listn1

那么,找到listn1的总和并减去listn2中的项目:

def sum_until(l, max):
    return sum([x for x in l if x < max])

listn2 = list(set(listn2))

for n1 in listn1:
    finish = max_n // n1
    s += n1 * (finish * (finish + 1) / 2 - sum_until(listn2, finish)) 

修改

我猜NumPy的总和会更快。使listn2成为一个numpy数组:

import numpy as np

listn2 = np.array(list(set(listn2))) 

并使用此sum_until函数:

def sum_until(listn2, max):
    l = listn2[np.where(listn2 <= max)]
    return int(np.sum(l))

答案 1 :(得分:0)

根据建议,我重新编写了代码

setn2 = set(listn2)
s = 0
for n1 in listn1:
    s += n1 * (max_n * (max_n + 1) // 2 - sum(i for i in range(1, 1 + max_n // n1) if i in setn2))

而不是几小时,总和现在需要几秒钟。