Реализации алгоритмов/Метод бисекции: различия между версиями

Материал из Викиучебника — открытых книг для открытого мира
Содержимое удалено Содержимое добавлено
→‎На языке C: обновление данных
Строка 15: Строка 15:
int n = 0; // задаём переменной тип целая и начальное значение;
int n = 0; // задаём переменной тип целая и начальное значение;
xd = xr - xl; // вычисляем длину отрезка;
xd = xr - xl; // вычисляем длину отрезка;
while ( abs(f(xl))>EPS || abs(f(xr)>EPS ) { // пока абсолютные значения функции больше заданной точности делаем;
while ( abs(f(xl))>EPS || abs(f(xr))>EPS ) { // пока абсолютные значения функции больше заданной точности делаем;
n = n + 1; // прибавляем 1 в счётчик числа проходов (делений на 2, итераций);
n = n + 1; // прибавляем 1 в счётчик числа проходов (делений на 2, итераций);
xd = xd / 2; // вычисляем длину новых отрезков;
xd = xd / 2; // вычисляем длину новых отрезков;

Версия от 18:17, 27 мая 2012

Численные методы.
Метод деления отрезка пополам (метод бисекции).

На языке C

                   
#include <stdio.h>                  // подключаем к компилятору библиотеку stdio.h;  
#include <math.h>                   // подключаем к компилятору библиотеку math.h;
#define EPS 1e-10                   // задаём точность результата 1*10^(-10)

double f(double x) {                // задаём вызываемой функции и аргументу - тип двойной точности;  
   return exp(x) - 2 - x;           // задаём описание функции f(x); 
}

int main ( ) {                      // главная часть программы; 
   double xl = 0, xr = 2, xm, xd, signfxl, signfxm; // задаём переменным тип двойной длины и начальные значения; 
   int n = 0;                       // задаём переменной тип целая и начальное значение;
   xd = xr - xl;                    // вычисляем длину отрезка;
   while ( abs(f(xl))>EPS || abs(f(xr))>EPS ) {  // пока абсолютные значения функции больше заданной точности делаем;  
      n = n + 1;                    // прибавляем 1 в счётчик числа проходов (делений на 2, итераций);
      xd = xd / 2;                  // вычисляем длину новых отрезков;  
      xm = xl + xd;                 // вычисляем значение x в середине отрезка;
      signfxl = copysign(1, f(xl)); // придаём единице знак f(xl); 
      signfxm = copysign(1, f(xm)); // придаём единице знак f(xm);
       
      if ( signfxl != signfxm )     // узнаём, находится ли искомое приближение к корню в левой части; 
         xr = xm;                   // берём левую часть;
      else                          // иначе искомое приближение к корню находится в правой части;
         xl = xm;                   // берём правую часть;                    
   }

   printf ("Value of function: %.10lf\n", f(xm));      // выводим значение функции вблизи корня
   printf ("Left bound equal: %.10lf\n", xl );         // выводим xl
   printf ("Middle of line segment: %.10lf\n", (xl + xr) / 2);  // выводим приближение к корню
   printf ("Right bound equal: %.10lf\n", xr );        // выводим xr
   printf ("Numbers of iterations equal: %10i\n", n ); // выводим число проходов (делений на 2, итераций) n
}

В результате прогона программы на устройстве ввода-вывода должен получиться следующий вывод:

Value of function:           -0.0000000027
Left bound equal:             1.1461932193
Middle of line segment:       1.1461932203  
Right bound equal:            1.1461932212
Numbers of iterations equal:         30

На языке Matlab

Пример реализации алгоритма на языке Matlab:

 
  clear;
  
  %Интервал
  x_L=1;
  x_R=2;
  length=x_R-x_L;
  %Начальная ошибка
  err=length;
  
  %Итерационный цикл
  while err>1e-3
      %Деление отрезка пополам
      x_M=(x_L+x_R)/2;
      %Нахождение нового интервала
      if tan(x_L)*tan(x_M)<0
          x_R=x_M;
      else
          if tan(x_M)*tan(x_R)<0
              x_L=x_M;
          else
              x_M
              break;
          end
      end
      %Пересчёт ошибки
      err=(x_R-x_L)/length;
  end
  %Вывод результата
  x_M
  err

Результат выполнения вполне ожидаемый:

  x_M =
  
      1.5713
  
  
  err =
  
    9.7656e-004