Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции АиП.doc
Скачиваний:
92
Добавлен:
15.11.2018
Размер:
668.67 Кб
Скачать
    1. Метод половинного деления

Метод половинного деления называется также методом дихотомии (от греческого – разделяю на две части). Англоязычные народы называют его method of bisection. Этот метод не самый скорый, однако наиболее надежный. Он использует следующий принцип: если корень находится в интервале , то произведение .

При использовании метода дихотомии вначале определяют точку в середине отрезка: . Затем находят значение функции в этой точке . Если , то корень заключен в интервале , а если , то – в интервале . Далее операцию деления повторяют с тем отрезком, в котором может находиться корень. Итерации продолжают до тех пор, пока интервал поиска не станет меньше заданной малой величины :

.

Исходный интервал уменьшается до после одного деления. А после делений уменьшается до величины . Приравнивая , и решая это уравнение относительно , получим

. (7.3)

В листинге 7.2 представлена программа, решающая заданное уравнение методом половинного деления. Для определения количества делений используется формула (7.3). В данной программе помимо основной функции main() содержатся также функции Bisect()и Func(). В отличие от предыдущего примера (листинг 7.1) данные для вычислений вводятся в самой функции Bisect(), а функция main() используется только для вызова функции Bisect(). Такой подход считается более приемлемым.

Входной аргумент filter предназначен для |контролируфильтрации возможной сингулярности. Устанавливая filter=1, мы заставляем программу проверять, уменьшается ли величина функции с каждым делением интервала пополам. Если нет, искомый «корень», является не корнем, а сингулярностью. Если есть уверенность, что сингулярность в данной задаче отсутствует, следует установить: filter=0.

Листинг 7.2. Решение уравнения методом дихотомии

#include <iostream.h>

#include <math.h>

int Bisect(); // Прототипы функций

double Func(double p[], int n, double x);

void main()

{

Bisect();

}

int Bisect()

{

int i, n, k, filter;

double p[10];

double a, b, x1, x2, x3, f1, f2, f3, tol, root;

cout<<"Input degree of polynomial: ";

cin>>n;

cout<<endl;

cout<<"Input function:\n";

for (i=0; i<(n+1); i++)

{

cin>>p[i];

}

cout<<endl;

cout<<"Input left limit: ";

cin>>a;

cout<<endl;

cout<<"Input right limit: ";

cin>>b;

cout<<endl;

cout<<"Input tol: ";

cin>>tol;

cout<<endl;

//filter=singularity filter: 0=off (default), 1=on.

cout<<"Input filter (0 or 1): ";

cin>>filter;

cout<<endl;

f1=Func(p, n, a);

if (f1==0.0)

{

root=a;

cout<<"Root: "<<root<<"\n";

char Res;

cin>>Res;

return 0;

}

f2=Func(p, n, b);

if (f2==0.0)

{

root=b;

cout<<"Root: "<<root<<"\n";

char Res;

cin>>Res;

return 0;

}

if (f1*f2>0)

{

cout<<"Root is not bracketed in ("<<a<<", "<<b<<")"<<"\n";

char Res;

cin>>Res;

return 0;

}

k=ceil(log(fabs(b-a)/tol)/log(2.0));

x1=a;

x2=b;

for (

i=1; i<(k+1); i++)

{

x3=0.5*(x1+x2);

f3=Func(p, n, x3);

if ((filter==1)&&(fabs(f3)>fabs(f1))&&(fabs(f3)>fabs(f2)))

{

cout<<"Root is not bracketed in ("<<a<<", "<<b<<")"<<"\n";

char Res;

cin>>Res;

return 0;

}

if (f3==0.0)

{

root=x3;

cout<<"Root: "<<root<<"\n";

char Res;

cin>>Res;

return 0;

}

if (f2*f3<0.0)

{

x1=x3;

f1=f3;

}

else

{

x2=x3;

f2=f3;

}

}

root=0.5*(x1+x2);

cout<<"Root: "<<root<<"\n";

char Res;

cin>>Res;

return 0;

}

double Func (double p[], int n, double x)

{

double Sum=0;

double y=1;

for (int i=0; i<(n+1); i++)

{

Sum=Sum+p[i]*y;

y=y*x;

}

return Sum;

}