繁体   English   中英

python 中的嵌套求和

[英]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

我至少看到以下选项(按提高效率排序):

只是可读的 Pythonic 方式

关于 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM