Бесконечный цикл в делении пополам Ньютона

#fortran #fortran90 #gfortran

#fortran #fortran90 #gfortran

Вопрос:

 program main
implicit none
double precision x0, a, b
x0 = -3

call findzero(x0)

contains


function f(x)
implicit none
double precision x,f

f = SIN(x) - exp(-x)

end function

function fprime(x)
implicit none
double precision fprime, x

fprime = COS(x)   exp(-x)

end function

subroutine findbracket(x0,a,b)
implicit none
double precision x0, a, b
double precision fa, fb
double precision dx

dx = 0.001d0
a = x0
b = x0

do
fa = f(a)
fb = f(b)
!print*,"bracket[", a, b, "]"  

    a = a - dx

    if (fa*fb < 0) then
        exit
    end if

    b = b   dx

    if (fa*fb < 0) then
        exit
    end if

    dx = dx*2

end do

end subroutine


subroutine findzero(x0)
implicit none
double precision x0, a, b
double precision p, tol


while (x0 <11) do 
    x0 = -3 
    print*, "what is x0", x0
    call findbracket(x0,a,b)

    call newtonbisection (p,a,b,tol)
    print*, "this is x0, x", x0, p
    x0 = x0   1

end do

end subroutine
  

Используя эту подпрограмму, я пытаюсь решить для нулей

f(x) = sinx - e^-x

с x0 = -3, -2, ..., 10 помощью .

У меня есть рабочие подпрограммы findbracket и newtonbisection . Используя findbracket , я намереваюсь получить [a,b] и используя эти a и b, я хочу найти p для каждого x0.

Когда я компилирую, мой код попадает в бесконечный цикл, я попробовал это с комментированием

 call newtonbisection (p,a,b,tol)
  

итак, я предполагаю, что проблема в findbracket с. Но если я просто использую подпрограмму для поиска [a,b] x0 = -3 , она работает, но не тогда, когда я их объединяю.

Почему у меня бесконечный цикл?

Комментарии:

1. Похоже, вы не заканчиваете subroutine findbracket , это опечатка?

2. Это тип. Я только что отредактировал. Извините за это.

3. можете ли вы объяснить, как вы ожидаете, что последний цикл выполнения завершится?

4. Извините за еще одну ужасную опечатку.. Я пробовал много разных способов решения проблемы и немного запутался. Я попытался while (x0 <11) do , чтобы x0 = 10 могло быть последней итерацией, но у меня все еще была та же проблема.

5. И вы все еще не последовали совету, данному в комментарии к одной из более ранних версий этого вопроса, использовать отступы для отражения структуры вашего кода.

Ответ №1:

Давайте сузим этот цикл:

  do while (x0 < 11)
    x0 = -3
    call findbracket(x0, a, b)
    x0 = x0   1
end do
  

Это цикл, который выполняется до тех пор, пока x0 он меньше одиннадцати. Внутри цикла вы явно устанавливаете x0 значение минус 3, затем вызываете подпрограмму, которая использует x0 , наконец, increment x0

Я не видел ни одного места внутри findbracket подпрограммы, где значение x0 было бы изменено, поэтому оно все равно будет -3 в конце вызова. Затем он увеличивается на единицу, так что теперь -2 он все еще меньше 11 , поэтому цикл начинается снова. Первое, что он делает, это сбрасывает x0 значение -3 , и весь текст снова начинается с той же точки.

Таким образом, условие x0 < 11 всегда будет истинным, поскольку на каждой итерации x0 будет сброшено на -3 . Цикл никогда не завершится. Ваша программа зависает.

Вам нужно переместить x0 = -3 до перед циклом, вот так:

 x0 = -3
do while (x0 < 11) 
    call findbracket(x0, a, b)
    x0 = x0   1
end do
  

Таким образом, x0 значение не будет сбрасываться -3 на каждой итерации цикла и в конечном итоге станет больше, чем 11 так, чтобы цикл заканчивался.

Ответ №2:

«Бесконечный» цикл for достигается следующим образом:

 do

   ** Some executable statements

   if (conditional_statement) exit
end do 
  

Вкратце, набор операторов выполняется повторно до тех пор, пока не будет удовлетворен условный оператор, то есть,

 conditional_statement .eqv. .true.
  

Когда это происходит, управление программой переходит к следующему исполняемому оператору сразу после do построения.

Комментарии:

1. К вашему сведению, бесконечные циклы предпочтительнее do while флагов оптимизации помощи.

2. Я попытался сделать x0 =-3, if (x0 == 10) then exit но он все равно попадает в бесконечный цикл.. Извините, что пишу все коды в одной строке

3. Это просто говорит вам, что x0 никогда не увеличивается на 10 . Следовательно, виновата одна из ваших нижних подпрограмм.