6

これが私のサンプルコードです。これは、ガウス・ザイデル(行列ソルバー)の反復手順となることを目的としています。基本的に、エラーが十分に小さい場合、whileループから抜け出します。

i=1
while (i>0):
    x_past = x_present

    j=0
    while(j<3):
        value=0
        k=0
        while(k<3):
            if(k!=j):
                if(i==1):
                    if(k>j):
                        value=value+0
                    else:
                        value=value+x_present[k]*eqn[j][k]    
                else:
                    value=value+x_present[k]*eqn[j][k]
            else:
                value=value+eqn[j][k]
            k=k+1
        x_present[j:j+1]=[value]
        j=j+1
    print "X_PAST"
    print x_past
    print "X_PRESENT"
    print x_present    
    if(error(x_past, x_present)<10**-2):
        break;
    i=i+1

コードを減らして管理しやすくしました。あなたがそれが何をしているのか理解していないなら、それはこの問題を解決するのにそれほど重要ではありません。

これが問題です。毎回

x_present[j:j+1]=[value]

が実行されると、x_pastはx_presentと等しくなります。x_pastをx_presentに設定したのはループの一番上だけなので、なぜこれが当てはまるのかわかりません。私が奪うなら

x_past=x_present

文では、x_pastがx_presentと等しくなることはありません。これにより、問題の原因は2つのステートメントの組み合わせであると思います。

これは、x_past =x_presentが毎回エラー=0であり、最初の反復後にループが中断する場合の大きな問題の原因です。コードは機能します。たとえば、コードに8回の反復を実行するように指示し、ブレークすると、想定される答えが得られます。

私は過去4時間これを理解しようとしてきましたが、完全に困惑しています。私は長い間Pythonを使用していないので、構文に関するトラブルシューティングスキルはそれほど優れていません。どんな助けでもいただければ幸いです!!

4

6 に答える 6

31

はい、ここでの答えはあなたの問題を示していると思います。少しだけ明確にしてみてください。

リストを参照しているので、リストが変更されると、そのリストへの参照はその変更を反映します。実証するために:

>>> x_present = [4,5,6]
>>>
>>> x_past = x_present
>>>
>>> x_past
[4, 5, 6]
>>>
>>> x_present.append(7)
>>>
>>> x_past
[4, 5, 6, 7]
>>>

リストのコピーが必要な場合は、これを行う必要があります。listcopy= mylist [:]。(またimport copy;listcopy = copy.copy(mylist)

>>> x_past = x_present[:]
>>> x_past
[4, 5, 6, 7]
>>>
>>> x_present.append(8)
>>>
>>> x_past
[4, 5, 6, 7]
于 2008-11-05T08:13:16.343 に答える
4

x_pastとx_presentとは何ですか?Pythonについてはよくわかりませんが、.NET / Javaの観点からは、データ構造(マップなど)への参照である場合、(最初に行うように)同じオブジェクトへの参照にすることを意味します。一方の変数を介して行われた変更は、もう一方の変数を介して表示されます。参照の割り当てを行うだけでなく、データ構造のコピーを取得する必要があるようです。使用しているデータ構造には、何らかの「クローン」機能がありますか?

私が言っているように、私はPythonをあまり知らないので、これは完全に間違っている可能性があります...

于 2008-11-05T08:00:34.807 に答える
3

他の人が指摘したように、答えは replace: x_past = x_presentbyx_past = x_present[:]です。一般に、copyモジュールを使用して Python でオブジェクトをコピーできます。

>>> import copy
>>> a = range(10)
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> b = a
>>> a += 10, 11
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
>>> b
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
>>> c = copy.copy(a) # shallow copy
>>> c
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
>>> del a[3:]
>>> a
[0, 1, 2]
>>> b
[0, 1, 2]
>>> c
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

あなたのコードは控えめに言っても非Pythonicです。

次のコードのようなものに置き換えることができます。

import copy
# assert(len(x_present) >= len(eqn))

first = True
while True:
    x_past = copy.copy(x_present) # copy

    for j, eqj in enumerate(eqn):
        x_present[j] = sum(x_present[k] * eqj[k] 
                           for k in range(j if first else len(eqj)) 
                           if k != j)
        x_present[j] += eqj[j] 

    print "X_PAST\n%s\nX_PRESENT\n%s" % (x_past, x_present)
    if allequal(x_past, x_present, tolerance=10**-2):
        break
    first = False

(絶対誤差を使用した場合の定義は次のallequal()とおりです。あなたの場合、それは良い考えかもしれませんし、そうでないかもしれません(代わりに相対誤差を使用することもできます)):

def allequal(x, y, tolerance):
    return (len(x) == len(y) and 
            all(-tolerance < (xx - yy) < tolerance
                for xx, yy in zip(x, y)))
于 2008-11-05T09:50:22.090 に答える
1

Pythonでは、すべてがオブジェクトです。したがって、ステートメントx_past=x_presentは同じ参照を指します。

于 2008-11-05T08:36:39.993 に答える
0

x_presentがリストのように見えます。これは、割り当てx_last = x_presentがx_lastをエイリアスにすること、つまり同じ変数を参照することを意味していると思います。これは事実でしょうか?

于 2008-11-05T08:02:06.303 に答える
0

x_past = x_present行をに変更してみてx_past = [x for x in x_present]、それが役立つかどうかを確認してください。

リストコピーの省略形は、他の言語では不可能なワンライナーを実行できるため、私のお気に入りのPython機能です。

greaterthan100 = [x for x in number if x > 100]

notinblacklist = [x for x in mylist if x not in blacklist]

firstchildofbigfamily = [x.child[0] for x in familylist if len(x.child) > 10]

于 2008-11-05T08:14:10.303 に答える