[英]Nested summation in python
我正在尝试在 python 中执行以下嵌套求和:
所以我尝试了以下代码:
import numpy as np
gamma = 17
R = 0.5
H = np.array([0.1,0.2])
alpha = np.array([0.1,0.2])
n = 2
F = 0
for i in range(n):
for j in range(i+1):
F = F + 3*gamma*H[i]*(R+H[j]*np.tan(alpha[j]))**2
但是,当然,这并没有给我正确的答案,因为它在j
循环中再次对所有项求和。 我的问题是我该如何解决? 请记住,这只是一个大表达式的一小部分,其中j
有几个求和,就像上面的i
求和一样,所以它必须进行一些优化。 先感谢您!
在这种情况下, for
循环与∑
非常相似,即公式中∑
之外的所有内容都应该在for
循环之外,即:
...
F = 0
for i in range(n):
inner_sum = 0
for j in range(i+1):
inner_sum += H[j] * np.tan(alpha[j])
F += 3 * gamma * H[i] * (R + inner_sum) ** 2
我至少看到以下选项(按提高效率排序):
关于 python 的一件好事是,您可以将这些表达式写成非常类似于数学中的写法。 在您的情况下,您想对一个iterable
的数字sum
:
f = sum(
3 * gamma * H[i] * (
R + (
sum(
H[j] * np.tan(alpha[j])
for j in range(i+1)
)
)
)**2
for i in range(n)
)
在您的情况下,内部总和
sum(
H[j] * np.tan(alpha[j])
for j in range(i+1)
)
被计算多次,而它只是在每次迭代中递增。 让我们将这个术语inner_sum(index)
。 那么inner_sum(index-1)
已经在之前的迭代中计算过了。 因此,当我们在每次迭代中重新计算它时,我们会浪费时间。 一种方法是使inner_sum
成为 function 并缓存其先前的结果。 我们可以为此目的使用functools.cache
:
from functools import cache
@cache
def inner_sum(index: int) -> float:
if not index:
return H[0] * np.tan(alpha[0])
return inner_sum(H, index - 1) + H[index] * np.tan(alpha[index])
现在,我们可以写:
f = sum(
3 * gamma * H[i] * (
R + inner_sum(i)
)**2
for i in range(n)
)
这仍然不节省内存,因为我们将所有H[i] for i < index 存储在 memory 中,而实际上我们只需要最后一个。 有不同的方法来实现只存储最后一个值的 object。 例如,您可以将其存储在变量inner_sum_previous
中。 或者你可以让inner_sum
成为一个合适的生成器,一个接一个地吐出(实际上: yield
)部分和:
from typing import Generator
def partial_sum() -> Generator[float, None, None]:
partsum = 0
index = 0
while True:
try:
partsum += H[index] * np.tan(alpha[index])
yield partsum
index += 1
except IndexError:
raise StopIteration
有了这个,我们会写;
partial_sum_generator = partial_sum()
f = sum(
3 * gamma * H[i] * (
R + next(partial_sum_generator)
)**2
for i in range(n)
)
在j
循环中先计算括号内的部分,存入变量,然后乘以表达式的rest。
只是为了紧凑和可读性,我会用 go 来做这样的事情:
for i in range(n):
3*gamma*H[i]*(R + np.sum([H[j]*np.tan(alpha[i]) for j in range(i)]))**2
显然,您也可以将第一个 for 循环转换为列表上的总和,就像我对第二个求和所做的那样,以使表达式更紧凑,但我认为这种方式更具可读性。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.