0

x = 0 と x = pi の間の曲線 y=sin(x) の下の領域を計算する Python v. 2.7.5 を使用してプログラムを作成しようとしています。この計算を実行して、x の範囲を 1 ~ 10 の範囲で n 分割し、近似値、真の値、およびパーセント誤差を出力します (つまり、台形の数を増やすことで精度を上げます)。すべての値を小数点以下 3 桁まで出力します。

コードがどのように見えるべきかわかりません。これらの計算を行うには、約 12 行のコードしか必要ないと言われました。

Wing IDE を使用しています。

これは私がこれまでに持っているものです

# base_n = (b-a)/n
# h1 = a + ((n-1)/n)(b-a)
# h2 = a + (n/n)(b-a)
# Trap Area = (1/2)*base*(h1+h2)
# a = 0, b = pi

from math import pi, sin

def TrapArea(n):
for i in range(1, n):
    deltax = (pi-0)/n
    sum += (1.0/2.0)(((pi-0)/n)(sin((i-1)/n(pi-0))) + sin((i/n)(pi-0)))*deltax
    return sum

for i in range(1, 11):
    print TrapArea(i)

正しい軌道に乗っているかどうかはわかりません。「代入前にローカル変数 'sum' が参照されました。コードを改善する方法について何か提案はありますか?」というエラーが表示されます。

4

3 に答える 3

1

コードにいくつかのインデントの問題がありますが、それは単にコピー ペーストが原因である可能性があります。とにかくsum = 0、関数の先頭に行を追加するとTrapArea、現在のエラーが解決するはずです。しかし、コメントで @Blender が指摘したように、*浮動小数点除算式の後に乗算演算子 ()がないという別の問題があります(1.0/2.0)

Python では、数学的に期待するように式が常に評価されるとは限らないことに注意してください。したがって、数式で期待するようにby(a op b)(c)の結果を自動的に乗算することはありません。代わりに、これは Python の関数呼び出し表記です。a op bc

また、割り当てに値を使用する前に、すべての変数を初期化する必要があることにも注意してください。Python には名前のない変数のデフォルト値がないため、sumwithsum += exprと同等の値を参照すると、オブジェクトにまったくバインドされていないsum = sum + expr名前 ( ) を参照しようとしています。sum

関数の次のリビジョンでうまくいくはずです。*乗算するすべての式の間に乗算演算子 ( ) を配置する方法に注目してください。

def TrapArea(n):
    sum = 0
    for i in range(1, n):
        i = float(i)
        deltax = (pi-0)/n
        sum += (1.0/2.0)*(((pi-0)/n)*(sin((i-1)/n*(pi-0))) + sin((i/n)*(pi-0)))*deltax
    return sum

編集:ループのすべての反復内に変換iすることにより、浮動小数点数の問題にも対処しました。float(i)Python 2.x では、1 つの整数型オブジェクトを別の整数型オブジェクトで除算すると、式は実際の値に関係なく整数に評価されます。

于 2013-09-29T01:21:25.923 に答える
1

等間隔の点で台形規則を行う「より良い」方法...

を間隔dx = pi/nの幅とします。また、以下の式を短縮するために、f(i) を sin(i*dx) とします。次に、間隔 i (in range(1,n)) が寄与します。

dA = 0.5*dx*( f(i) + f(i-1) )

...合計に(これは面積なので、「デルタ面積」にdAを使用しています)。0.5*dx を因数分解すると、全体が次のようになります。

A = 0.5*dx * ( (f(0) + f(1)) + (f(1) + f(2)) + .... + (f(n-1) + f(n)) )

2 つの f(1) 項、2 つの f(2) 項、最大 2 つの f(n-1) 項があることに注意してください。それらを組み合わせて取得します:

A = 0.5*dx * ( f(0) + 2*f(1) + 2*f(2) + ... + 2*f(n-1) + f(n) )

0.5 と 2 の因数は、最初と最後の項を除いて相殺されます。

A = 0.5*dx(f(0) + f(n)) + dx*(f(1) + f(2) + ... + f(n-1))

最後に、dx を完全に因数分解して、最後に乗算を 1 回だけ行うことができます。sin() 呼び出しに戻すと、次のようになります。

def TrapArea(n):
    dx = pi/n
    asum = 0.5*(sin(0) + sin(pi))   # this is 0 for this problem, but not others
    for i in range(1, n-1):
        asum += sin(i*dx)
    return sum*dx

それは「合計」を「asum」に変更したか、「面積」の方が良いでしょう。これは主に、sum() が組み込み関数であるためです。これを行の下で使用します。


追加クレジット: 合計のループ部分は、ジェネレーター式と sum 組み込み関数を使用して 1 つのステップで実行できます。

def TrapArea2(n):
    dx = pi/n
    asum = 0.5*(sin(0) + sin(pi))
    asum += sum(sin(i*dx) for i in range(1,n-1))
    return asum*dx

それらの両方をテストします。

>>> for n in [1, 10, 100, 1000, 10000]:
        print n, TrapArea(n), TrapArea2(n)

1 1.92367069372e-16 1.92367069372e-16
10 1.88644298557 1.88644298557
100 1.99884870579 1.99884870579
1000 1.99998848548 1.99998848548
10000 1.99999988485 1.99999988485

math.sin(math.pi) は正確にゼロではなく約 1.2e-16 に評価されるため、最初の行は「数値ゼロ」です。0 から pi までの 1 つの間隔を描画すると、エンドポイントは両方とも 0 (またはほぼ 0) になります。

于 2013-09-29T03:29:48.380 に答える