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ラムダ関数を使用することをお勧めします。

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

thenindexは単に「関数に渡される変数」であるため、必要ありません (名前は必要ありません)。

次に、関数は次のようになります

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

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 に答える