02.03.2009, 12:21
общий
это ответ
Здравствуйте, Fan1111!
Я представляю несколько другой вариант, более "автоматизированный", в котором учтена быстрота изменения функции
Приложение:
{$N+,E+}
{буду передавать подпрограммам функции как параметры.
Нужно такое определение нового типа}
{Есть два варианта метода хорд. Я не буду использовать тот, что описан
http://machinelearning.ru/wiki/index.php?title=Методы_дихотомии
Использую второй вариант, где применяются два значения xk и xk-1
чуть быстрее}
type
float = extended; {так можно менять точность вычисления - Real, Double}
TFunction = function (x: float): float;
CONST
maxSteps: longint = 100000;
{Глобальные переменные}
var
ln10: float;
eps : float;
function f(s: float): float; far;
{Для передаваемой функции обзаательно определить ее как дальний тип
иначе будет сформирован адрес только в виде смещения в памяти
А механизм передачи требует полный адрес}
begin
f := 2*s -ln(s)/ln10 - 7;
end;
function df(s: float): float; far;
begin
df := 2 - 1/(s*ln10)
end;
function chord(func: TFunction; a, xk: float; tol: float): float;
{Для начала работы нужны две точки - вот их и передаем как параметры}
{В качестве критерия окончания поиска решения всегда принимается
ордината
И еще ограничим максимальное число шагов - не всегда сходится
В данном-то случае сойдется, но ...}
var dx, f_k, f_k1: float;
steps: Longint;
begin
steps := 1;
tol := tol + eps;
f_k := func(a);
f_k1:= func(xk);
dx := 4*tol; {чтоб сразу не окончился, а потом будет вычисляться}
repeat
write(steps:8); { выключи, если не хочешь смотреть, за сколько шагов)
{dx = x_k+1 - x_k. То есть потом будет x_k+1 = x_k + dx}
dx := - f_k/((f_k - f_k1)/(xk - a));
a := xk;
{заданная функция очень быстро изменяется. По это причине,
если неудачно задать начальные точки, легко получить отрицательное
число. По этой причине ввел ограничение}
while (xk + dx) <= 0 do dx := dx/10;
xk := xk + dx;
f_k1 := f_k;
f_k := func(xk);
inc(steps);
until (steps > maxSteps) or (abs(dx) < tol);
WriteLn;
chord := xk;
end;
function Newton(func: TFunction; a: float; tol: float): float;
var fk, dx : float;
steps : Longint;
begin
tol := tol + eps;
steps := 1;
repeat
write(steps:8);
dx := - f(a)/df(a);
while (a + dx) <= 0 do dx := dx/10;
a := a + dx;
inc(steps);
until abs(dx) < tol;
Writeln;
Newton := a
end;
BEGIN
{тонкость = машинная точность = минимальное число, уже воспринимаемое
машиной как ноль. То есть самая маленькая точность, которая может быть
задана. Нужно для того, чтобы пользователь не заморачивался такими
вещами}
eps := 1; while 1 + eps > 1 do eps := eps/2;
eps:=eps*4; {один раз деление было произведено зря. И двойку накидываю
еще для верности}
ln10 := ln(10);
{Вычисление методом хорд с максимальной точностью}
WriteLn(chord(f, 7e-6, 2e-6, 0));
{Вычисление методом Ньютона или касательных}
WriteLn(Newton(f, 7e-6, 0));
END.