这是我的示例代码。它是高斯塞德尔(矩阵求解器)的迭代过程。基本上当错误足够小时,它就会突破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。这使我认为这是导致问题的两个陈述的某种组合。
如果每次x_past = x_present错误= 0并且第一次迭代后循环中断,则这是一个很大的问题。代码确实有效,例如,如果我告诉代码运行8次迭代并且中断它给了我应该的答案。
我一直试图在过去的4个小时内解决这个问题并且完全被困住了。我没有使用python很长时间,所以我的麻烦射击技巧语法明智不是那么好。任何帮助将不胜感激!!
答案 0 :(得分:30)
是的,我认为这里的答案显示了您的问题。 只是试着澄清一下。
您正在引用列表,因此当列表更改时,对该列表的任何引用都将反映该更改。为了证明:
>>> 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 [:] 。
>>> x_past = x_present[:]
>>> x_past
[4, 5, 6, 7]
>>>
>>> x_present.append(8)
>>>
>>> x_past
[4, 5, 6, 7]
答案 1 :(得分:4)
什么是x_past和x_present?我不太了解Python,但是从.NET / Java的角度来看,如果它们引用了某些数据结构(地图或其他),那么让它们引用同一个对象(就像你在开始时那样)将意味着通过一个变量进行的任何更改都将通过另一个变量可见。听起来您需要获取数据结构的副本而不是仅仅执行引用分配。您正在使用的数据结构是否具有任何类型的“克隆”功能?
正如我所说,我不太了解Python,所以这可能是完全错误的......
答案 2 :(得分:3)
正如其他人所指出的那样,答案是将x_past = x_present
替换为x_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]
至少可以说你的代码是单声道的。
可以用以下代码替换它:
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)))
答案 3 :(得分:1)
在Python中,一切都是对象。 所以语句x_past = x_present指向相同的引用。
答案 4 :(得分:0)
看起来x_present是一个列表。我怀疑这意味着赋值x_last = x_present使x_last成为别名,即它们引用相同的变量。情况可能会这样吗?
答案 5 :(得分: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]