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

Материал из Викиучебника — открытых книг для открытого мира
Содержимое удалено Содержимое добавлено
Метка: possible spambot (testing)
Метка: possible spambot (testing)
Строка 48: Строка 48:
Пример реализации алгоритма на языке [[w:Matlab|Matlab]]:
Пример реализации алгоритма на языке [[w:Matlab|Matlab]]:
<big><source lang="Matlab">
<big><source lang="Matlab">
function [res, error] = bisection(fun, left, right, tol)
function [res, err] = bisection(fun, left, right, tol)
if fun(left)*fun(right) > 0
if fun(left)*fun(right) > 0
error('Значения функции на концах интервала должны быть разных знаков');
error('Значения функции на концах интервала должны быть разных знаков');

Версия от 20:45, 14 июня 2014

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

На языке 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:

 
function [res, err] = bisection(fun, left, right, tol)
   if fun(left)*fun(right) > 0
      error('Значения функции на концах интервала должны быть разных знаков');
  %Деление отрезка пополам
   middle = 0.5*(left +right);
  %Итерационный цикл
   while abs(fun(middle)) > tol     
     %Нахождение нового интервала
      left = left*(fun(left)*fun(middle) < 0) + middle*(fun(left)*fun(middle) > 0);
      right = right*(fun(right)*fun(middle) < 0) + middle*(fun(right)*fun(middle) > 0);
     %Деление нового интервала пополам
      middle = 0.5*(left +right);
   end
   res = middle;
   err = abs(fun(middle));

Пример работы алгоритма для поиска корня функции y = tan(x) на интервале [1; 2] с точностью 1e-3. Результат вполне ожидаемый:

[res, err] = bisection('tan', 1, 2, 1e-3)  
res =
  
      1.5713
  
err =
  
    9.7656e-004