Вот мой пример кода. Это задумано как итеративная процедура для гаусс-зейделя (решателя матриц). По сути, когда ошибка достаточно мала, она выходит из цикла 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, так что мои навыки поиска и устранения проблем с синтаксисом не так уж хороши. Любая помощь будет оценена по достоинству!
Да, это, наверное, самый ужасный фрагмент кода Python, который я когда-либо видел. Python некрасив, если вы слишком далеко его вложили, так что не надо :)
О, мама миа! Ужасный код =)






Что такое x_past и x_present? Я не очень хорошо разбираюсь в Python, но с точки зрения .NET / Java, если они ссылаются на некоторую структуру данных (карту или что-то еще), то создание их ссылок на один и тот же объект (как вы делаете в начале) будет означать что любые изменения, внесенные через одну переменную, будут видны через другую. Похоже, вам нужно сделать копию структуры данных, а не просто выполнять присвоение ссылки. Имеется ли в структуре данных, с которой вы работаете, какие-либо функции «клонирования»?
Как я уже сказал, я не очень хорошо знаю Python, так что это может быть совершенно неправильно ...
Да, но все же: дать ответ, а затем признать, что он может быть «совершенно неправильным», не добавляет никакой полезной информации в обсуждение.
@hop: Да, это так - он предлагает OP попробовать. Здесь три варианта: 1) Ничего не говорите - это совсем не поможет. 2) Скажите что-нибудь, не объясняя неопределенности. Ложная уверенность - это нехорошо. 3) Объясните неопределенность (как я) - это честно и не дает ложных надежд.
Как обычно, даже когда Джон Скит не знает конкретного языка программирования, оказывается, что язык программирования делает именно то, что, по его мнению, он делает.
Похоже, что x_present - это список. Я подозреваю, что это означает, что присвоение x_last = x_present превращает x_last в псевдоним, т.е. они ссылаются на одну и ту же переменную. Может ли это быть так?
в python нет переменных, только имена. и уж точно никаких псевдонимов.
@hop: если вы вводите несколько привязок имен к одному объекту, это можно рассматривать как псевдоним. По крайней мере, термин «свободная переменная» присутствует в Python.
Да, я думаю, что ответы здесь показывают вашу проблему. Просто чтобы попытаться немного уточнить.
Вы ссылаетесь на список, поэтому при изменении списка любая ссылка на этот список отразит это изменение. Показывать:
>>> 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]
попробуйте изменить строку 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]
В Python все является объектом. Таким образом, выражение x_past = x_present указывает на ту же ссылку.
Совсем неправда. >> x = 5 >> y = x >> x = 8 >> вывести x, y 8 5
@kigural: Вы запутались. Переназначение x, конечно, не влияет на y. Эдди считает, что если вы измените объект, на который указывает x, видимое значение y также изменится, что правильно.
Как указывали другие, ответ заключается в замене: 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)))
спасибо за предыдущий сол за копирование списков. Однако код, который вы дали мне для замены кода, который у меня есть, не работает. Проблема, похоже, заключается в x_present [j] = sum (x_present [k] ...
@darudude: Для кода sum(.. требуется версия Python> = 2.5 Какую версию вы используете?
@darudude: Я проверил, нет ли синтаксических ошибок на Python 2.5.2 в приведенном выше коде. Не знаю, верна ли семантика. Приведенный выше код является простой иллюстрацией того, как код Python отличается от кода в стиле C, Fortran.
Это дает мне право просматривать кого-то. при пробуждении. Мои глаза болят!