1

我正在创建一个 sigsum() 函数,该函数使用输入方程和输入变量求和。这是我到目前为止所拥有的:

def sigsum(eqn, index, lower=0, upper=None, step=1):

    if type(step) is not int:
        raise TypeError('step must be an integer')
    elif step < 1:
        raise ValueError('step must be greater than or equal to 1')

    if upper is None:
        upper = 1280000

    if lower is None:
        lower = -1280000

    if (upper - lower) % step:
        upper -= (upper - lower) % step

    index = lower
    total = 0
    while True:
        total += eqn
        if index == upper:
            break
        index += step

    return total

函数用法:

print(sigsum('1/(i+5)','i'))
>>> 12.5563

我当前的问题是将“eqn”和“index”转换为函数本地命名空间中存在的变量。我听说使用 exec 不是一个好主意,也许 setattr() 可能会起作用。谁能帮我吗?谢谢。

4

2 回答 2

2

因为eqn我建议使用 lambda 函数:

eqn = lambda i: 1 / (i + 5)

然后index不需要,因为它只是“传递给函数的变量”(不需要名称)。

然后你的功能变成

def integrate(fn, start = 0, end = 128000, step = 1):
    """
    Return a stepwise approximation of
      the integral of fn from start to end
    """
    num_steps = (end - start) // step
    if num_steps < 0:
        raise ValueError("bad step value")
    else:
        return sum(fn(start + k*step) for k in range(num_steps))

你可以像这样运行它

res = step_integrate(eqn)   # => 10.253703030104417

请注意,这有很多步骤,其中许多涉及非常小的数字;舍入错误可能成为一个主要问题。如果准确性很重要,您可能需要手动导出积分,

from math import log

eqn          = lambda i: 1 / (i + 5)
eqn.integral = lambda i: log(i + 5)

def integrate(fn, start = 0, end = 128000, step = 1):
    """
    Return the integral of fn from start to end

    If fn.integral is defined, used it;
    otherwise do a stepwise approximation
    """
    if hasattr(fn, "integral"):
        return fn.integral(end) - fn.integral(start)
    else:
        num_steps = (end - start) // step
        if num_steps < 0:
            raise ValueError("bad step value")
        else:
            return sum(fn(start + k*step) for k in range(num_steps))

这又像

res = step_integrate(eqn)   # => 10.150386692204735

(请注意,逐步逼近大约高了 1%。)

于 2015-01-31T02:36:31.253 回答
1

我会使用 lambda 函数,因为 Hugh Bothwell 建议您必须将 sigsum 修改如下

def sigsum(eqn, lower=0, upper=None, step=1):

    if type(step) is not int:
        raise TypeError('step must be an integer')
    elif step < 1:
        raise ValueError('step must be greater than or equal to 1')

    if upper is None:
        upper = 1280000

    if lower is None:
        lower = -1280000

    if (upper - lower) % step:
        upper -= (upper - lower) % step

    index = lower
    total = 0
    while True:
        total += eqn(index)
        if index == upper:
            break
        index += step

    return total

函数用法:

print(sigsum(lambda i: 1/(i+5)))
>>> 12.5563

您还可以单独定义一个函数:

def myfunction(i):
     return 1/(i+5)

并将其传递给 sigsum

print(sigsum(myfunction))
>>> 12.5563

能够将函数作为参数传递在计算机语言语音函数中被称为第一类对象。(例如 C 和 java 没有,javascript 和 python 有)

于 2015-01-31T02:43:12.673 回答