我在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)
问题:这种方法很懒散。计算listn1
和listn2
需要几秒钟,因此我知道要添加的数字超过一百万。但我昨天晚上开始总结,今天早上还在运行。
是否有一种Pythonic方法来加速这个求和?
答案 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))
而不是几小时,总和现在需要几秒钟。