Проблема с записью цикла для метода секущих в python

Недавно я начал изучать Python, и одной из задач на моем курсе было программирование метода секущих. У меня проблемы с переназначением переменных в цикле.

Независимо от того, как я пишу оператор while, я продолжаю получать ошибку деления на ноль. Я предполагаю, что это потому, что мой код делает циклы текущими x_1=x_0 и вычисляет f(x_1)-f(x_0), а не использовать старый x_1 вместо x_0. Моя попытка:

G = 6.6741*10**-11
r_e = 6371000
r_m = 1737100
M_e = 5.9722*10**24
M_m = 7.3420*10**22
R = 3.8440*10**8
w =  2.6617*10**-6

def f(x):
    return (G*M_e)/x**2 - (G*M_m)/(R-x)**2 - w**2 * x

x_0=2*10**8
x_1=2.2*10**8

i=1

while i<=10 or 0.99 < x_1/x_0 <1.01:
    x_1=float(x_1-f(x_1)*(x_1-x_0)/(f(x_1)-f(x_0)))
    i = i+1
    x_0=x_1

print (x_1)

Ошибка:

runfile('//myfiles/vj284/dos/python/Coursework q1.py', 
wdir='//myfiles/vj284/dos/python')
Traceback (most recent call last):

  File "<ipython-input-2-b33827a1b929>", line 1, in <module>
    runfile('//myfiles/vj284/dos/python/Coursework q1.py', 
wdir='//myfiles/vj284/dos/python')

   File "C:\Program Files\Anaconda3\lib\site- 
packages\spyder\utils\site\sitecustomize.py", line 705, in runfile
    execfile(filename, namespace)

  File "C:\Program Files\Anaconda3\lib\site- 
packages\spyder\utils\site\sitecustomize.py", line 102, in execfile
    exec(compile(f.read(), filename, 'exec'), namespace)

  File "//myfiles/vj284/dos/python/Coursework q1.py", line 20, in <module>
    x_1=float(x_1-f(x_1)*(x_1-x_0)/(f(x_1)-f(x_0)))

ZeroDivisionError: float division by zero
Почему бы не загружать изображения кода на SO при задании вопроса? ... Скопируйте и вставьте текст, затем отформатируйте его как код (выделите его и введите ctrl-k) ... stackoverflow.com/help/formatting ... stackoverflow.com/editing-help
wwii 08.04.2019 20:03
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
1
144
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

I am assuming this is because my code is making the loops current x_1=x_0 and computing f(x_1)-f(x_0), rather than using the old x_1 for x_0.

Неа. Это из-за вашей последней строчки в цикле x_0 = x_1. Почему вы перезаписываете x_0? Кроме того, для чего y?

Обновлено: поскольку вы добавили текстовую версию, исправить код стало проще. Просто используйте временную переменную для хранения «нового» результата. Кроме того, измените or на and И добавьте условие для проверки сходимости (если метод сходится, x_0 будет таким же, как x_1, и поэтому код вылетит из-за деления на ноль):

i = 1
while i <= 10 and 0.99 < x_1/x_0 <1.01 and abs((x_1 - x_0) / x_1) > 1e-15: :
    tmp = x_1 - f(x_1) * (x_1 - x_0) / (f(x_1) - f(x_0))
    i = i + 1
    x_0 = x_1
    x_1 = tmp

Непонятно, почему у вас есть and 0.99 < x_1/x_0 <1.01 в условии цикла. Я думаю, вы должны просто удалить его:

i = 1
while i <= 10 and abs(x_1 - x_0) > 1e-15 * abs(x_1):
    tmp = x_1 - f(x_1) * (x_1 - x_0) / (f(x_1) - f(x_0))
    i = i + 1
    x_0 = x_1
    x_1 = tmp

Последнее редактирование: чтобы избежать необходимости во временной переменной, я бы переписал цикл следующим образом:

for _ in range(10):
    if abs(x_1 - x_0) < 1e-15 * abs(x_1):  
        break  
    x_0, x_1 = x_1, x_1 - f(x_1) * (x_1 - x_0) / (f(x_1) - f(x_0)) 

Более того, возможно, стоит проверять близость значений функции, а не ее аргументов: часто из-за ошибок округления f(x_1) может быть равно f(x_0), хотя x_1 != x_0. Или вы можете проверить, что f(x_1) <= eps указывает, что корень найден.

Извините, y была еще одной переменной, введенной в предыдущей попытке посмотреть, смогу ли я ее обойти, плохо отредактирую свой вопрос и удалю ее. Я думал, что он установит x_0 как старый x_1, но теперь я понимаю, что это не произойдет, поскольку x_1 уже был переопределен. Однако сделать заявление раньше все равно не помогает.

Vishal Jain 08.04.2019 20:13

просто интересно, почему вы умножаете 1e-15 на x_1, разве установка abs(x_1-x_0)< 1e-15 не будет работать так же хорошо?

Vishal Jain 10.04.2019 10:38

@VishalJain См. en.wikipedia.org/wiki/Machine_epsilon«Машинный эпсилон дает верхнюю границу относительная ошибка» (в примере я просто приблизил машинный эпсилон к 1e-15). Если корень уравнения, скажем, x=1000, то наименьшее число, которое вы можете добавить к x и получить другое число, будет примерно x*eps (~ 1e-12). Вот почему вам нужно умножить 1e-15 (эпсилон) на abs(x_1)

AGN Gazer 10.04.2019 20:16

Другие вопросы по теме