изменение метода regula falsi на метод secant

#c #numerical-methods

#c #численные методы

Вопрос:

Я реализовал метод regula falsi. Я пытаюсь изменить его, чтобы он стал методом secant. В PDF-файле, который я прочитал, упоминалось, что это, по сути, то же самое, только с одним изменением. Будущие предположения для моего значения ‘m’ должны иметь немного другую формулу, вместо:

 m = a - f(a) * ( (b-a)/( f(b)-f(a) ) );
  

это должно быть:

 m = a - f(a) * ( (m-a)/( f(m)-f(a) ) );
  

но, к сожалению, это не работает (он никогда не находит корень). Что я должен исправить, чтобы перенести это в метод secant?

исходный код выглядит следующим образом:

 #include <stdio.h>
#include <math.h>


void
secant(double a, double b, double e, double (*f)(double), int maxiter ) {
  double m, fm, fa, fb;
  int i;

  fa=(*f)(a);
  fb=(*f)(b);

  m = a - fa * ( (b-a)/( fb - fa ) );

  fm=(*f)(m);


   for(i=0; i<maxiter; i  ) {
    if ( fabs(fm) <= e ) {                               
      printf("f(%f) = %fn", m, fm);
      return;
    } else if ((fa*fm) < 0) {
      b=m;
      fb=fm;
    } else {
      a=m;
      fa=fm;
    }

     // the guess below works for regula falsi method:   
     // m = a - fa * ( (b-a)/(fb - fa)); 

     //this was supposed to be the change to turn this into the secant method 
     m = a - fa * ( (m-a)/(fm - fa) ); 

     fm=(*f)(m);
  }
}

int main(){
secant(1,4,0.0001,sin,500);
return 0;
}
  

Заранее спасибо

РЕДАКТИРОВАТЬ: Хорошо, поиграв с ручкой и бумагой, я, наконец, понял, что это было не простое изменение, как я изначально думал:

 void secant(double a, double b, double e, double (*f)(double), int maxiter ) {
  double m, fm, fa, fb;
  int i;
  fa=(*f)(a);
  fb=(*f)(b);

   for(i=0; i<maxiter; i  ) {
     m = a - fa * ( (b-a)/(fb - fa) );
     fm=(*f)(m);
     if ( fabs(fm) <= e ) {                               
        printf("f(%f)=%f, iter: %dn", m,fm,i);
         return;
     }
     a=b;
     b=m;
     fa=fb;
     fb=fm;
  }
}
  

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

1. «не работает»? Не могли бы вы быть более конкретными? Происходит ли сбой программы, не сходится ли она, сходится ли слишком медленно, существует ли предельный цикл или он ускорился до бесконечности? Или происходит что-то еще…

2. Упс. Я только что пояснил, что он не находит корень функции

Ответ №1:

Методу secant проще не находить корень. Вы уверены, что он должен его найти?

Для тестирования вот пример:http://www.mathcs.emory.edu/ccs/ccs315/ccs315/node18.html (пример 4.7) Вы бы хотели запустить этот пример ( f (x) = x ^ 6-x-1, x0 = 1 x1 = 2, корень x = 1,347)

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

1. спасибо, только что протестировал его, и метод secant занимает 6 итераций, тогда как первоначальный метод regula falsi занял 1360, так что, я думаю, он работает так, как рекламируется

Ответ №2:

Либо PDF неверен, либо вы его неправильно поняли. Без чтения PDF невозможно сказать, какой именно, или объяснить дальше. Когда я объясняю оба метода, я говорю, что разница между regula falsi и методом secant заключается в правиле обновления a и b.

Вычислите первые две итерации метода secant вручную. Затем измените свою программу, чтобы выводить значения a, b и m на каждой итерации (или используйте отладчик). Это должно дать вам представление о том, что происходит.

В вашем примере метод secant должен сходиться за несколько итераций.

Ответ №3:

Метод Secant — это метод с открытыми скобками, тогда как Regula-Falsi имеет тип с закрытыми скобками. Итак, ваш PDF-файл верен. Чтобы изменить метод Regula-Falsi на метод secant, вы должны изменить тип закрытых скобок на открытый.

Смотрите этот пример для метода Regula-Falsi. Здесь кодирование таково, что один интервал всегда остается постоянным.

Теперь, вот пример программы для метода Secant. Здесь, как и в методе Regula, принимаются два начальных предположения, но оба интервала продолжают меняться до тех пор, пока не будет получен правильный корень. Получите начальные два предположения вручную.

И, что касается скорости сходимости, для метода Secant она суперлинейна, тогда как для Regula она линейна. Таким образом, метод secant сходится намного быстрее.