Program _Approc_;{Аппроксимация функций методом наименьших квадратов}
{$E-,N+,G+,D+}
Uses Graph, CRT;
type
Sto = array [ 1..70 ] of Extended;
const
n = 10;
x0 : Extended = 1.0;
xn : Extended = 4.0;
Yb : Integer = 464;
var
m, nn, k, p, s : Byte;
Dr, R, e : Integer;
y : array [0..n] of Extended;
dx, ymax, ymin, x : Extended;
A : array [ 1..70 ] of Sto;{Массив }
B : Sto ;
i, j : Longint;
Function f(x, d, g, p, q, m, k, l : Extended):Extended;{Сама функция}
begin
f := (d+exp((p*x+q)*ln(x)))*exp(m*x*x+k*x+l);
end;
Procedure Swap(p, q: Byte);
var
j : Byte;
X : Extended;
begin
for j:=1 to nn do
begin
X := A[p,j];
A[p,j] := A[q,j];
A[q,j] := X;
end;
X := B[p];
B[p] := B[q];
B[q] := X;
end;
Procedure Divid(p : Byte; k : Extended);
var
j : Byte;
begin
for j := 1 to nn do
A[p, j] := A[p, j] / k;
B[p] := B[p] / k;
end;
Procedure Sub(p, q : Byte);
var
j : Byte;
begin
for j := 1 to nn do
A[p, j] := A[p, j] - A[q, j];
B[p] := B[p] - B[q];
end;
Function CheckNullStr(p : Byte): Boolean;
var
i : Byte;
k : Extended;
begin
k := 0;
for i := 1 to nn do
k:=k + Abs (A[p, i]);
CheckNullStr := ((k=0) and (B[p]=0));
end;
Function BadStr(p : Byte) : Boolean;
var
i : Byte;
k : Extended;
begin
k := 0;
for i := 1 to nn do
k:=k + Abs (A[p, i]);
BadStr := ((k=0) and (B[p]<>0));
end;
Procedure KillNullStr(r : Byte);
begin
Swap(r, m);
dec(m);
end;
Function IsZeroDiag : Boolean;
var
i : Byte;
q : Boolean;
begin
q := false;
for i := 1 to m + 1 do
q := q or (A[i,i] = 0) ;
IsZeroDiag := q;
end;
Procedure FindNZD ;
var
i : Byte;
begin
for i := k+1 to m + 1 do
if A[i,k] <> 0.0 then
begin
Swap(k, i);
end;
end;
Procedure SolveMattr;
var
i : Byte;
Label
Loop;
begin
k := 1;
Loop:
While k <= m+1 do {???}
begin
for i := 1 to m+1 do
if not BadStr(i) then
begin
if CheckNullStr(i) then
begin
KillNullStr(i);
goto loop;
end;
end
else {ViewResult(0)};
FindNZD;
p:=0;
for i := k to nn do
if A[k,i] = 0 then inc(p)
else Break;
for i := 1 to m + 1 do
if A[i,k+p]<>0 then
Divid(i, A[i,k+p]);
for i :=1 to m + 1 do
if (i<>(k+p)) and (A[i,k+p]<>0.0) then
Sub(i,k+p);
inc(k);
end;
for i:=1 to m + 1 do if A[i,i]<>0 then
Divid(i,A[i,i]);
i := 1;
While i <= m + 1 do
begin
{ if BadStr(i) then {ViewResult(0);}
if CheckNullStr(i) then KillNullStr(i);
inc(i);
end;
end;
Function Xdg(x, dg : Extended):Extended;
begin
Xdg := exp(dg*ln(x));
end;
Function Fi(x:Extended):Extended;
var
tmp : Extended;
k : Word;
begin
tmp := 0;
for k := 0 to m do tmp := tmp + B[k+1]*Xdg(x, 1.0*k);
Fi := tmp;
end;
Procedure CalledKeyProc;
begin
x := x0;
dx := (xn-x0)/1000.0;
While x <= xn do
begin
PutPixel(20+Round((x-x0)/(xn-x0)*600),Yb-Round((Fi(x)-ymin)/(ymax-ymin)*450), LightRed);
x := x + dx;
end;
end;
Function Max(Ar : array of Extended) : Extended;
var
Mx : Word;
j : Word;
begin
Mx := 0;
for j := 0 to n do
if Ar[Mx]Ar[j] then Mn := j;
Min := Ar[Mn];
end;
Procedure SetMattr;
var
i, k : Word;
tmp : Extended;
begin
for s := 0 to m do {по строкам}
begin
for k := 0 to m do {По элементам строки}
begin
tmp := 0.0;
for i := 0 to n do
tmp := tmp + Xdg(x0+dx*i, 1.0*(k+s));
A[s+1, k+1] := tmp;
end;
tmp := 0.0;
for i := 0 to n do
tmp := tmp + y[i]*Xdg(x0+dx*i, 1.0*s);
B[s+1] := tmp;
end;
end;
Procedure ScreenMattr;
var
i, j : Byte;
begin
Writeln;
for i := 1 to m+1 do
begin
{ for j := 1 to nn do
Write(A[i, j]:1:3,' ');}
WriteLn('a',i-1,':| ',B[i]:1:3);
end;
ReadKey;
end;
Function Dispersia : Extended;
var
i : Longint;
tmp : Extended;
begin
tmp := 0; {!!!!!!!!!!!!!}
for i := 0 to n do
tmp := tmp + sqr(y[i]-Fi(x0+dx*i));
Dispersia := tmp/(n+1);
end;
begin
Randomize;
m := 15;
nn := m+1;
ClrScr;
dx := (xn-x0)/n;
for i := 0 to n do
{ y[i] := 50 + (2.0*Random - 1.0)+i*1.0;}
y[i] := f(x0+dx*i, 0, 1.2, 0.002, -1.001, 0, -0.001, 0);
ymax := Max(y);
ymin := Min(y);
SetMattr;
SolveMattr;
ScreenMattr;
Dr := Detect; {Инициализируем графику}
InitGraph(Dr, R, '');
e := GraphResult;
if e <> grOk then {Если ошибка}
begin
WriteLn('Ошибка инициализации графики!');
WriteLn(GraphErrorMsg(e));
ReadKey;
Halt($FFFF);
end;
MoveTo(20, Yb-Round((y[0]-ymin)/(ymax-ymin)*450));
SetColor(LightGreen);
Circle(20, Yb-Round((y[0]-ymin)/(ymax-ymin)*450), 1);
for i := 1 to n do
begin
SetColor(Yellow);
LineTo(20+Round(i*dx/(xn-x0)*600), Yb-Round((y[i]-ymin)/(ymax-ymin)*450));
SetColor(LightGreen);
Circle(20+Round(i*dx/(xn-x0)*600), Yb-Round((y[i]-ymin)/(ymax-ymin)*450), 1);
end;
ReadKey;
CalledKeyProc;
ReadKey;
CloseGraph;
dx := (xn-x0)/n;
for i := 0 to n do
WriteLn(i, ' : ', x0+dx*i:1:3, ' -> ', sqr(Fi(x0+dx*i)-y[i]));
Write('Дисперсия равна: ');
WriteLn(Dispersia:1);
Write('Среднеквадратичное отклонение равно: ');
WriteLn(sqrt(Dispersia):1);
ReadKey;
end.