Учебник Turbo Pascal. Введение - Вычисление корня функции методом деления отрезка пополам
ОГЛАВЛЕНИЕ
Вычисление корня функции методом деления отрезка пополам
В следующем примере запрограммировано вычисление корня функции методом деления отрезка пополам. Напомню, что корень функции F(x) — это такое значение ее аргумента х*, при котором выполняется условие F(x*) = 0. Известно, что для решения такого уравнения надо вначале задать интервал [а, Ь], на котором будет искаться решение. Если решение действительно существует, принадлежит заданному интервалу и является на этом интервале единственным, функция F(x) принимает на границах интервала значения противоположных знаков. Другими словами, произведение значений функции на границах интервала отрицательно: F(a)F(b) < 0. Далее исходный интервал делится средней точкой с = (а+b)/2 на две равные части, из которых выбирается лишь та, которая содержит решение уравнения. Процедура деления отрезка пополам повторяется до тех пор, пока корень функции не будет найден с заданной точностью. Оценкой погрешности в данном случае может быть величина последнего интервала |а-b| или значение |F(x)|. Последний критерий используется в программе, приведенной в листинге 1.11.
Листинг 1.11. Решение нелинейного уравнения методом деления отрезка пополам
{$N+}
program bisection;
type
real_function = function (x: Real): Real;
function G(x: Real): Real; far;
begin
G := Sqr(x) - 2.0;
end;
function zero(F: real_function; x, y: Real): Real;
const
eps = 1.0e-12;
var
mid, fx, fy, fm: Real;
begin
fx := F(x);
fy := F(y);
if fx * fy > 0.0 then
Halt; {Прекращение работы подпрограммы, если на выбранном участке нет корня}
repeat
if Abs(fx) < eps then
begin
zero := x;
Exit;
end
else if Abs(fy) < eps then
begin
zero := y;
Exit;
end
else begin
mid := 0.5 * (x + y);
fm := F(mid);
if fx*fm <= 0 then
begin
у := mid;
fy := fm;
end
else begin
x := mid;
fx := fm;
end;
end
until false;
end;
begin
WriteLn('G(', zero(G, 1.0, 2.0):10:10, ') = 0');
ReadLn;
end.
Остановимся подробнее на этой программе. Вторая строка содержит оператор type, разговор о котором пойдет позже. Сейчас же скажу, что этот оператор позволяет программисту ввести свой собственный тип. Слева от знака равенства записывается название нового типа данных, а справа задается сам этот тип. В нашем случае это функциональный тип. В третьей строке программы используется новый для нас элемент — ключевое слово far. Это директива компилятора, которая используется в описаниях подпрограмм, передаваемых в качестве параметров другим подпрограммам. Такой подпрограммой в нашем случае является подпрограмма-функция G. Она используется в качестве аргумента другой подпрограммы-функции zero. В функции zero запрограммировано вычисление корня произвольной непрерывной функции, имеющей на границах исходного интервала противоположные знаки. Использование функции G в качестве аргумента подпрограммы-функции zero делает программу более универсальной, ведь для решения другого нелинейного уравнения достаточно будет подставить в данную программу описание другой функции.
Оператор цикла repeat...until... в программе сделан бесконечным, так как условие завершения — просто логическая константа false. Если окажется, что корень функции найден с заданной точностью, будет выполняться условный оператор, следующий сразу же за заголовком цикла, а его выполнение завершится вызовом процедуры Exit. Эта процедура завершает выполнение функции. Если условие противоположности знаков нарушено, процедура Halt остановит выполнение программы. В этом случае у функции на заданном интервале нет корня.