Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Раздел 3_4.pdf
Скачиваний:
11
Добавлен:
11.02.2016
Размер:
854.55 Кб
Скачать

Функция Power предназначена для возведения значения Xx в целую степень P. Функция Deg_Rad предназначена для перевода значения угла Gr из градусной

меры в радианы.

4.4 Примеры использования предопределенных процедур.

Пример №1 Отделение корней путем анализа графика функции.

Использование некоторых подпрограмм модуля Librery1 рассмотрим на примере нахождения корня уравнения:

f(x) =k1 x cos(k2 x) =0

(3.26)

где k1 и k2 - коэффициенты функции.

Сначала произведем отделение корней с использованием графического представления функции на экране монитора. Для этого разработана программа Sample_1.

В этой программе вслед за заголовочным оператором помещается ключевое слово uses после которого располагается список имен модулей к процедурам которых будут обращения в теле программы. В данном случае это модули Librery1 и Crt. Следует обратить также внимание на использование в данной программе определения типа переменных Vec, принятого в модуле Library1. При определении функции F используются глобальные переменные K1 и K2 отражающие значения коэффициентов уравнения. Поэтому соответствующие формальные и фактические параметры, отражающие значения коэффициентов уравнения носят одинаковые имена. Такой прием обеспечивает определенные удобства, но в некоторых случаях опасен (когда программа громоздка, а пользователь недостаточно компетентен). Все формальные параметры функции F параметры - значения, поэтому ключевое слово var перед списком формальных параметров не ставится.

В программе после ввода исходных данных производится (в цикле) расчет значений аргумента и функции. Затем осуществляется обращение к процедуре Grafic. Обратите внимание на то, что при обращении к процедуре Grafic формальные параметры, отражающие маркеры и точки излома линии графика совпадают. Следовательно, на графике маркеры будут расположены в точках излома. К выбору количества точек на графике следует подходить осторожно. Большое количество точек (а следовательно и маркеров) затруднит рассмотрение графика, малое количество плохо отразит особенности функции. Разумным представляется назначить N = 20 – 50.

Ниже приводится текст программы Sample_1.pas, протокол ввода данных и график функции выводимый на экран монитора.

program Sample_1; (* Рисование графика функции *) uses Library1, Crt;

var

N,I : Integer; X,Y : Vec;

K1,K2 : Real; Xmin,Xmax,Dx : Real; function F(XX:Real):Real; begin

F:=K1*XX-cos(K2*XX);

100

end;

 

 

begin

 

 

ClrScr;

Коэффициенты функции:');

Writeln('

Write('

k1=');

Readln(K1);

Write('

k2=');

Readln(K2);

Write('

Количество точек на оси X - N='); Readln(N);

Write('

xmin=');

Readln(Xmin);

Write('

xmax=');

Readln(Xmax);

Dx:=(Xmax-Xmin)/(N-1);

for I:=1 to N do

 

begin

 

 

X[I]:=Xmin+Dx*(I-1);

Y[I]:=F(X[I]);

 

end;

 

 

Grafic(N,X,Y,N,X,Y);

 

Readln;

 

 

end.

 

 

Протокол ввода данных при выполнении программы Sample_1:

Коэффициенты функции:

 

k1=

0.200

 

k2=

2.000

 

Количество точек на оси X - N=50

xmin=

0.000

 

xmax= 10.000

 

 

 

 

Рис. 3.4 Изображение на экране монитора графика выводимого программой Sample_1

101

Как видно из рис. 3.4 уравнение (3.26) в положительной части оси x имеет три корня x1 0.7, x2 2.7, x3 3.5.

Пример № 2. Уточнение значения корня методом Ньютона.

В качестве примера демонстрирующего уточнение значения корня уравнения (3.26) методом Ньютона рассмотрим программу Sample_2.pas. В этой программе производится обращение к процедуре Newton определенной в модуле Librery1. Будем искать уточненное значение только первого корня так, как уточнение остальных корней производится аналогично.

Обратим внимание на определение функции Fdivdf, которая отражает отношение функции (3.26) к ее производной. В нашем случае:

f

=

( k1 x cos( k 2

x )

(3.27)

f '

( k1 + k 2 sin( k 2

x )

 

 

Поскольку в приведенной программе используется обращение к функции (Fdivdf), определенной пользователем в самой программе, как к параметру, то необходимо задать директиву компилятору {$F+}, определяющую модель дальнего вызова процедур и функций.

program Sample_2; (* Поиск корня уравнения методом Ньютона *) uses Library1,Crt;

var

K1,K2,X,E : Real; {$F+}

function Fdivdf(X:real):Real; begin

Fdivdf:=(K1*X-cos(K2*X))/(K1+K2*sin(K2*X)); end;

begin

ClrScr;

Writeln('Значения коэффициентов функции:');

Write('

k1=');

Readln(K1);

Write('

k2=');

Readln(K2);

Write('Начальное приближение X0='); Readln(X); Write('Абсолютный итерационный допуск e='); Readln(E); Newton(X,E,Fdivdf);

Writeln('Значение корня X=',X:8:3); Readln;

end.

Протокол обмена программы Sample_2:

Значения коэффициентов функции: k1=0.2

k2=2.0

Начальное приближение X0=0.700 Абсолютный итерационный допуск e=0.005

Значение корня X=

0.714

102

Пример № 3. Уточнение значения корня методом половинного деления.

В программе Sample_3.pas уточнение значения корня производится с использованием метода половинного деления (процедура Dix определенная в модуле Library1).

program Sample_3; uses Library1,Crt; var

Kod : Integer; A,B,K1,K2,X,E : Real;

{$F+}

function F(X:Real):Real; begin

F:=K1*X-cos(K2*X); end;

begin

ClrScr;

Writeln('Границы интервала:');

Write('

a=');

Readln(A);

Write('

b=');

Readln(B);

Writeln('Коэффициенты функции:');

Write('

K1=');

Readln(K1);

Write('

K2=');

Readln(K2);

Write('Абсолютный итерационный допуск e='); Readln(E); Dix(A,B,E,X,F,Kod);

if Kod=0 then Writeln('Значение корня X=',X:8:3)

else Writeln('Значение корня вне заданного интервала!'); Readln;

end.

Протокол обмена программы Sample_3:

Границы интервала: a= 0.00

b= 1.00

Коэффициенты функции: K1= 0.20

K2= 2.00

Абсолютный итерационный допуск e=0.00500 Значение корня X= 0.715

Пример № 4. Уточнение значения корня методом хорд.

В программе Sample_4.pas уточнение значения корня производится с использованием метода хорд (процедура Chord определенная в модуле Library1).

program Sample_4; (* Нахождение корня методом хорд *) uses Library1,Crt;

var

Kod : Integer;

103

A,B,K1,K2,X,E : Real; {$F+}

function F(X:Real):Real; begin

F:=K1*X-cos(K2*X); end;

begin

ClrScr;

Writeln('Границы интервала:');

Write('

a=');

Readln(A);

Write('

b=');

Readln(B);

Writeln('Коэффициенты функции:');

Write('

K1=');

Readln(K1);

Write('

K2=');

Readln(K2);

Write('Абсолютный итерационный допуск e='); Readln(E); Chord(A,B,E,X,F,Kod);

if Kod=0 then Writeln('Значение корня X=',X:8:3) else begin

Writeln('*** Нет корня в заданном интервале'); Writeln('или на интервале несколько корней! ***');

end; Readln;

end.

Протокол обмена программы Sample_4:

Границы

интервала:

a=

0.00

b=

1.00

Коэффициенты функции:

K1=

0.20

K2=

2.00

Абсолютный итерационный допуск e=0.00500 Значение корня X= 0.714

Пример № 5. Решение СЛАУ методом Гаусса с выбором главного элемента.

 

Рассмотрим СЛАУ :

 

2 x1 + 1 x2 + 1 x3 = 7

 

1 x1 + 3 x2 + 1 x3 = 10

(3.28)

1 x1 + 2 x2 + 3 x3 = 14

Для нахождения решения рассмотренной СЛАУ будем использовать процедуру Gauss, определенную в модуле Library1. Для удобства ввода значений коэффициентов матрицы и вектора правых частей используем процедуру VvodA, определенную в том же модуле. Проверку решения осуществим путем сравнения правых частей уравнений (заданных и полученных путем подстановки решения в уравнения СЛАУ).

program Sample_5; uses Library1,Crt; var

104

I,J,N :

Integer;

A :

Mat;

X

:

Vec;

S,P

:

Real;

begin

ClrScr;

VvodA(N,A);

Gauss(N,A,X,S);

if S=0.0 then begin

Write('Матрица вырожденная'); Readln;

Exit;

end else begin

Writeln('Решение СЛАУ методом Гаусса.'); for I:=1 to N do

Writeln('

x[',I:2,']=',X[I]:10:3);

end;

Проверка

***');

Writeln('***

for I:=1 to N

do begin

 

P:=0.;

for J:=1 to N do P:=P+A[I,J]*X[J];

Writeln('i=',I:2,'

задано b=',A[I,N+1]:8:3,

end;

'

получено b=',P:8:3);

 

 

 

 

Readln;

 

 

 

 

end.

 

 

 

 

Протокол обмена программы Sample_5:

 

Ввод данных для решения СЛАУ

 

Порядок СЛАУ

N= 3

 

a[i,j]

Ввод значений коэффициентов матрицы

и элементов

вектора правой части

b[i)]

-------------------------------------------------

i - индекс

строки,

j - индекс столбца;

-------------------------------------------------

a[ 1, 1]=

2.000

 

 

 

a[ 1, 2]=

1.000

 

 

 

a[ 1, 3]=

1.000

1]= 7.000

 

a[ 2, 1]=

b[

 

1.000

 

 

 

a[ 2, 2]=

3.000

 

 

 

a[ 2, 3]=

1.000

2]= 10.000

 

a[ 3, 1]=

b[

 

1.000

 

 

 

a[ 3, 2]=

2.000

 

 

 

a[ 3, 3]=

3.000

3]= 14.000

 

 

b[

 

Решение СЛАУ методом Гаусса.

 

x[ 1]=

1.000

 

 

x[ 2]=

2.000

 

 

105

x[ 3]=

3.000

***Проверка ***

i= 1

задано b=

7.000

получено b=

7.000

i=

2

задано

b=

10.000

получено

b=

10.000

i=

3

задано

b=

14.000

получено

b=

14.000

Пример № 6. Решение СЛАУ методом Зейделя.

Для решения СЛАУ (3.28) итерационным методом Зейделя воспользуемся процедурой Zeidel, определенной в модуле Library1. Для проверки решения путем сравнения правых частей уравнений (заданных и полученных путем подстановки решения в уравнения СЛАУ) воспользуемся процедурой Testing, определенной в том же модуле...

program Sample_6; uses Library1,Crt; var

I,J,N,M : Integer;

A : Mat;

X : Vec;

E,P : Real; begin

ClrScr;

Write('Порядок матрицы N='); Readln(N); for I:=1 to N do begin

for J:=1 to N do begin

Write('a[',I:2,',',J:2,']='); Readln(A[I,J]); end;

Write('

b[',I:2,']='); Readln(A[I,N+1]);

end;

 

Write('Абсолютный итерационный допуск e='); Readln(E); Zeidel(N,A,X,E,M);

Writeln('Решение СЛАУ методом Зейделя.'); Writeln('Число итераций =',M:4);

for I:=1 to N do Writeln(' x[',I:2,']=',X[I]:10:3); Testing(N,A,X);

Readln; end.

Протокол обмена программы Sample_6:

Порядок матрицы N=3

a[ 1, 1]=

2.

a[ 1, 2]=

1.

a[ 1, 3]=

1.

b[ 1]=

7.

a[ 2, 1]=

1.

a[ 2, 2]=

3.

a[ 2, 3]=

1.

b[ 2]=

10.

a[ 3, 1]=

1.

a[ 3, 2]=

2.

a[ 3, 3]=

3.

106

 

b[ 3]= 14.

 

 

 

 

 

 

 

 

 

Абсолютный итерационный допуск e=0.005

 

 

 

Решение СЛАУ методом Зейделя.

 

 

 

 

 

Число итераций = 6

 

 

 

 

 

 

 

 

x[ 1]=

1.001

 

 

 

 

 

 

 

 

x[ 2]=

1.999

 

 

 

 

 

 

 

 

x[ 3]=

3.000

значений вектора правых частей СЛАУ

 

Проверка по невязке

 

i=1

 

заданное b=

7.000

 

 

 

 

 

 

i=2

полученное b=

7.001

 

 

 

 

 

 

 

заданное b=

10.000

 

 

 

 

 

 

i=3

полученное b=

9.999

 

 

 

 

 

 

 

заданное b=

14.000

 

 

 

 

 

 

 

полученное b=

14.000

 

 

 

 

 

 

Пример № 7. Аппроксимация табулированной функции полиномом.

 

 

Рассмотрим табулированную функцию:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

i

 

1

 

2

 

3

 

4

5

6

7

8

xi

 

0

 

0.15

 

0.27

 

0.43

0.52

0.65

0.81

1.0

yi

 

0

 

0.0.31

 

0.52

 

0.63

0.8

0.85

0.98

1.0

Необходимо данный набор значений отразить (аппроксимировать) полиномом второго порядка. Для аппроксимации воспользуемся процедурами Gram и Gauss, определенными в модуле Library1. Процедура Gram формирует матрицу Грамма, а процедура Gauss предназначена для решения СЛАУ методом Гаусса с выбором главного элемента. Кроме вывода полученных значений коэффициентов аппроксимирующего полинома в программе процедурой Grafic обеспечивается вывод результатов в виде графика. Причем заданные значения табулированной функции отражаются на графике маркерами, а результат аппроксимации - ломаной.

program Sample_7; uses Library1,Crt; var

I,J,K,L,N,M : Integer; Xmin,Xmax,Dx,Dy,S : Real;

X,Y,Xg,Yg : Vec; A : Mat; Koef : Vec;

begin

ClrScr;

Write(' Количество точек табулированной функции n='); Readln(N);

for I:=1 to N do begin

Write(' x[',I:2,']='); Read(X[I]);

Write(' y[',I:2,']='); Readln(Y[I]);

if (I=1) or (Xmin>X[i]) then Xmin:=X[i]; if (I=1) or (Xmax<X[i]) then Xmax:=X[i];

107

end;

Write(' Степень аппроксимирующего полинома k='); Readln(K);

M:=K+1;

Gram(N,A,X,Y,M,K);

Gauss(M,A,Koef,S); if S=0 then begin

Write('Матрица вырожденная!'); Readln;

Exit;

end else begin

Writeln('Коэффициенты аппроксимирующего полинома.'); Writeln(' y = a0 + a1*x + a2*x^2 +...+ ak*x^k');

for I:=1 to M do begin

Writeln(' a[',(i-1):1,']=', Koef[I]:10:4);

end; end;

Writeln('Результаты аппроксимации табулированной функции полиномом.');

for I:=1 to N do begin

S:=0.0;

for J:=1 to M do S:=S+Koef[J]*Power(X[I],(J-1)); Dy:=S-Y[I];

Writeln('X=',X[I]:8:3,'; Yтаб=',Y[I]:8:3, '; Yaпр=', S:8:3,'; dY=',Dy:8:5);

end; Readln;

(* Подготовка данных для построения графика *) Dx:=(xmax-xmin)/100.;

for I:=1 to 101 do begin

S:=0.0; xg[i]:=xmin+dx*(i-1);

for J:=1 to M do S:=S+Koef[J]*Power(Xg[I],(J-1)); Yg[i]:=S;

end; Grafic(N,X,Y,101,Xg,Yg);

end.

Протокол обмена программы Sample_7:

Количество точек табулированной функции n=8 x[ 1]=0.

y[ 1]=0.

x[ 2]=0.15

y[ 2]=0.31

x[ 3]=0.27

y[ 3]=0.52

x[ 4]=0.43

y[ 4]=0.63

x[ 5]=0.52

y[ 5]=0.80

108

 

x[ 6]=0.65

 

 

 

 

 

 

y[ 6]=0.85

 

 

 

 

x[ 7]=0.81

 

 

 

 

 

 

y[ 7]=0.98

 

 

 

 

x[ 8]=1.00

 

 

 

 

 

 

y[ 8]=1.00

 

 

 

 

Степень аппроксимирующего полинома k=2

 

Коэффициенты аппроксимирующего полинома.

 

 

y = a0 + a1*x + a2*x^2 +...+ ak*x^k

 

 

 

a[0]=

0.0210

 

 

 

 

 

a[1]=

1.9579

 

 

 

 

 

a[2]=

-0.9799

 

 

 

 

Результаты аппроксимации табулированной функции полиномом.

X=

0.000;

Yтаб=

0.000;

Yaпр=

0.021;

dY= 0.02098

X=

0.150;

Yтаб=

0.310;

Yaпр=

0.293;

dY=-0.01738

X=

0.270;

Yтаб=

0.520;

Yaпр=

0.478;

dY=-0.04183

X=

0.430;

Yтаб=

0.630;

Yaпр=

0.682;

dY= 0.05168

X=

0.520;

Yтаб=

0.800;

Yaпр=

0.774;

dY=-0.02589

X=

0.650;

Yтаб=

0.850;

Yaпр=

0.880;

dY= 0.02958

X=

0.810;

Yтаб=

0.980;

Yaпр=

0.964;

dY=-0.01607

X=

1.000;

Yтаб=

1.000;

Yaпр=

0.999;

dY=-0.00107

Графическое представление результатов аппроксимации на экране монитора приводится на рис.3.5.

Рис.3.5 Результат аппроксимации табулированной функции полиномом.

109

Пример № 8. Решение системы нелинейных алгебраических уравнений.

Существует много способов решения системы нелинейных алгебраических уравнений. Рассмотрим наиболее простой прием решения путем приведения системы нелинейных алгебраических уравнений к системе квазилинейных уравнений.

Пусть решению подлежит система алгебраических уравнений:

2 x12 + x 22 + 0.5 x 32 = 6.5;

 

x13

+ 3 x 2 + 0.5 x 33 = 7.5;

(3.29)

x12 + 0.5 x 2 + 3 x 32 = 5.

 

Для данной системы известно точное решение x1=1, x2=2, x3=1.

 

Систему нелинейных уравнений (3.29) можно привести к виду:

 

a11 x1 + a12 x12 + a13 x3 = a14 ;

 

a21 x1

+ a22 x12 + a23 x3 = a24 ;

(3.30)

a31 x1

+ a32 x12 + a33 x3 = a34

 

где

a11 = 2 x1;

a12 = x2; a13 = 0.5 x3;

a14 = 6.5;

 

 

a21 = x12;

a22 = 3 ;

a23 = 0.5 x32;

a24 = 7.5;

(3.31)

 

a31 = x1;

a32 = 0.5;

a33=3 x3;

a34 =5 .

 

Решение системы (3.30) будем вести итерационным методом. В начале зададимся

значениями x1, x2, x3 в первом приближении. Затем на каждой итерации будем рассчитывать значения коэффициентов согласно (3.31) и решать систему (3.30) методом Гаусса с главным элементом. Итерационный процесс завершим тогда, когда для каждого искомого значения xi выполнится условие:

xim xim1

≤ ε,

(3.32)

где ε – абсолютный итерационный допуск, m – номер итерации.

В некоторых случаях итерационный процесс может сходиться очень медленно или вообще быть расходящимся. Для обеспечения устойчивости и быстрой сходимости

итерационного процесса часто используют релаксационную формулу (3.33):

 

 

xim = ω xi + (1- ω) xim-1,

(3.33)

где xi

– решение, полученное на m-ой текущей итерации методом Гаусса,

 

xim-1 – решение, фиксированное на предыдущей итерации,

 

xim

- решение, принятое на текущей итерации,

 

ω - параметр релаксации; его значения должны находиться в диапазоне 0 ..1. Таким образом, в качестве результата на текущей итерации принимается некоторое значение лежащее между значением принятым на предыдущей итерации и решением, полученным методом Гаусса на текущей итерации. Чем меньше значение параметра релаксации, тем принятое решение ближе к результату предыдущей итерации. Если параметр релаксации равен 1, то влияние предыдущего приближения не учитывается. Изменяя значение ω можно в определенной мере управлять сходимостью итерационно-

го процесса решения системы уравнений вида (3.30).

Оговоренный подход реализован в программе Sample_7.pas. Константами в программе задаются: порядок матрицы N=3 и значение параметра релаксации W=0.5.

В программе определяется процедура Mm, предназначенная для пересчета значений коэффициентов матрицы. Для учета сходимости итерационного процесса вводится переменная Ig. В начале каждого прохода цикла Repeat – Until (итерации) значение Ig обнуляется. В процессе счета, если условие сходимости (3.32) не выполняется, к значению Ig прибавляется единица. Таким образом, только в том случае если для всех иско-

110

мых переменных выполнится условие (3.32), значение Ig к концу цикла останется равным нулю и можно будет завершить итерационный процесс.

Массив Xx отражает значения, принимаемые в качестве решения. Массив X отражает решение, полученное методом Гаусса.

В протоколе обмена приведены результаты итерационного решения.

program Sample_8; uses Library1,Crt; const N:Integer=3;

W:Real=0.5;

var

Iter,Ig,I,J : Integer; A : Mat;

XX,X : Vec;

E,S,P : Real;

procedure M(Var A:Mat; Var X:Vec); begin

A[1,1]:=2.*X[1]*X[1]; A[1,2]:=X[2]; A[1,3]:=0.5*X[3]; A[1,4]:=6.5; A[2,1]:=X[1]*X[1]; A[2,2]:=3.0; A[2,3]:=0.5*X[3]*X[3]; A[2,4]:=7.5; A[3,1]:=X[1]; A[3,2]:=0.5; A[3,3]:=3.0*X[3]; A[3,4]:=5;

end;

begin

ClrScr;

Writeln('Ввод начальных значений искомых величин:'); Write('X[1]='); Readln(Xx[1]);

Write('X[2]='); Readln(Xx[2]);

Write('X[3]='); Readln(Xx[3]); Write('Итерационный допуск E='); Readln(E); Iter:=0;

repeat

Iter:=Iter+1;

Ig:=0;

M(A,Xx);

Gauss(N,A,X,S);

for I:=1 to N do begin

if abs(Xx[I]-X[I])>E then Ig:=Ig+1; Xx[I]:=W*X[I]+(1.-W)*Xx[I];

end; until Ig=0;

Writeln('* Решение * Количество итераций =',Iter:3); for I:=1 to N do begin

111

Writeln(' x[',I:2,']=',X[I]:10:3); end;

Readln; end.

Протокол обмена программы Sample_8:

Ввод начальных значений искомых величин: X[1]=0.5

X[2]=0.5

X[3]=0.5

Итерационный допуск E=0.005

* Решение * Количество итераций = 21 x[1]= 1.003

x[2]= 1.996 x[3]= 0.999

112