
- •Предисловие
- •1. Общая схема решения задачи на персональном компьютере
- •2. Введение в язык Паскаль. Общая структура программы. Идентификаторы, комментарии, пробелы. Раздел описаний и раздел операторов
- •3. Арифметические типы данных. Числовые константы и переменные. Оператор присваивания. Выражения
- •Арифметические типы данных
- •4. Операторы ввода-вывода
- •5. Арифметические операции. Стандартные математические функции
- •Правила преобразования типов
- •6. Символьный тип данных
- •7. Логический тип данных. Операции сравнения. Логические операции. Битовые операции
- •Правила выполнения бинарных операций
- •8. Условный оператор. Блок. Оператор выбора
- •9. Операторы цикла
- •10. Метки. Оператор goto. Процедура Halt
- •11. Интервальные типы данных. Оператор type. Массивы
- •12. Ошибки при выполнении программы. Опции компилятора
- •13. Процедуры и функции. Сфера действия описаний
- •14. Множества
- •15. Тип string
- •16. Графические средства языка Паскаль
- •18. Записи
- •19. Тип "перечисление"
- •20. Модуль crt. Общие принципы организации интерфейса
- •21. Модули. Создание и использование модулей
- •Interface
- •Implementation
- •22. Файлы
- •23. Модуль dos и другие средства
- •24. Указатели и динамическая память
- •25. Динамические структуры: списки, деревья
- •26. Использование командной строки
- •27. Обработка программных прерываний
- •28. Параметры процедурных типов
- •29. Описатель absolute. Нетипизированные параметры. Открытые массивы
- •30. Вызов внешних пpогpамм
- •31. Некоторые вычислительные алгоритмы
- •Приближенное решение алгебраических уравнений
- •Решение систем линейных алгебраических уравнений
- •Аппроксимация таблично заданной функции методом наименьших квадратов
- •Численное интегрирование
- •Численное решение задачи Коши
- •32. Объекты
- •Содержание
Решение систем линейных алгебраических уравнений
Следующая группа вычислительных алгоритмов применяется для решения систем линейных алгебраических уравнений A·X=B. Для не слишком больших матриц применяют точный метод исключения Гаусса с выбором главного элемента. Система решается в два этапа: прямой ход приводит матрицу A к треугольному виду:
.
В начале каждого шага по k стрки расширенной матрицы системы переставляются таким образом, чтобы выполнилось условие
.
Обратный ход дает искомый вектор X :
.
Несколько модифицированный метод Гаусса можно с успехом применять для вычисления определителя и обратной матрицы. Запишем программу, реализующую этот метод:
CONST Nmax=40;
{Максимальный размер матрицы, вы можете выбрать другое число}
TYPE VectorType = ARRAY[1..Nmax] OF Real;
MatrixType = ARRAY[1..Nmax] OF VectorType;
FUNCTION Gauss( n : Byte {размер системы}; A : MatrixType {матрица системы};
B : VectorType {правые части}; VAR X : VectorType {вектор неизвестных}) : Boolean;
{ Функция будет возвращать TRUE, если систему удалось решить, и FALSE, если матрица системы вырождена }
VAR i,j,k,iMax : Byte; tmp,Max,d : Real; v : VectorType;
BEGIN FOR k:=1 TO n-1 DO BEGIN { прямой ход }
{ ищем главный элемент }
Max:=Abs(A[k,k]); iMax:=k;
FOR i:=k+1 TO n DO
IF Abs(A[i,k])>Max THEN BEGIN Max:=Abs(A[i,k]); iMax:=i; END;
IF Max=0 THEN BEGIN { матрица вырождена } Gauss:=FALSE; Exit; END;
IF iMax<>k THEN BEGIN { переставляем строки }
Tmp:=B[k]; B[k]:=B[iMax]; B[iMax]:=Tmp; v:=A[k]; A[k]:=A[iMax]; A[iMax]:=v; END;
FOR i:=k+1 TO n DO BEGIN {вычитаем из i-ой строки k-ю }
d:=A[i,k]/A[k,k];
FOR j:=k TO n DO A[i,j]:=A[i,j]-d*A[k,j];
B[i]:=B[i]-d*B[k]; END;
END;
{ сейчас матрица системы - треугольная }
IF A[n,n]=0 THEN BEGIN { матрица вырождена } Gauss:=FALSE; Exit; END;
{ обратный ход }
X[n]:=B[n]/A[n,n];
FOR i:=n-1 DOWNTO 1 DO BEGIN
tmp:=B[i];
FOR j:=i+1 TO n DO tmp:=tmp-A[i,j]*X[j];
X[i]:=tmp/A[i,i]; END;
Gauss:=TRUE;
END;
VAR n,i,j : Byte; a : MatrixType; b,x : VectorType;
BEGIN WRITE('Введите размер системы '); READ(n);
WRITELN('Введите расширенную матрицу системы');
FOR i:=1 TO n DO BEGIN
FOR j:=1 TO n DO READ(a[i,j]); READ(b[i]); END;
IF NOT Gauss(n,a,b,x) THEN BEGIN
WRITELN('Матрица системы вырождена'); Halt; END;
WRITELN('Решение системы и невязки :');
FOR i:=1 TO n DO BEGIN
FOR j:=1 TO n DO b[i]:=b[i]-a[i,j]*x[j];
WRITELN(x[i]:12,' ',b[i]:12); END;
END.
Хотя метод Гаусса и называют точным методом, невязки или погрешности, которые мы вывели в программе, не будут равны нулю. Но эти погрешности обусловлены не неточностью самого метода, а исключительно погрешностью вычисления арифметических операций.
Для очень больших систем, когда метод Гаусса становится неэффективным, применяют итерационные методы, например, метод простой итерации или метод Зейделя. Вычисления по методу простой итерации начинаются с произвольного вектора X0 ={x10, x20 ,..., xn0}. Итерационный процесс осуществляется по формуле:
,
т.е. все неизвестные на следующей итерации вычисляются только через неизвестные на предыдущей итерации.
В методе Зейделя используется итерационная формула
,
в которой при вычислении очередного неизвестного используются последние найденные значения остальных неизвестных. Вычисления заканчиваются, когда невязки системы становятся достаточно малыми. Итерационные методы сходятся не для всякой матрицы. Достаточным условием сходимости является положительная определенность матриц. Запишем программу, использующую метод простой итерации и метод Зейделя:
CONST Nmax=6;
TYPE VectorType = ARRAY[1..Nmax] OF Real;
MatrixType = ARRAY[1..Nmax] OF VectorType;
PROCEDURE SimpleIteration(n:Byte; A:MatrixType;B:VectorType;Epsilon:Real; VAR X:VectorType);
VAR i,k : Byte; X0 : VectorType; s,Max,Tmp : Real;
BEGIN X0:=X;
REPEAT
FOR i:=1 TO n DO BEGIN s:=B[i];
FOR k:=1 TO n DO s:=s-A[i,k]*X0[k]; X[i]:=X0[i]+s/A[i,i]; END;
{ Вычисляем максимальную невязку }
Max:=0;
FOR i:=1 TO n DO BEGIN Tmp:=Abs(X[i]-X0[i]);
IF Max<Tmp THEN Max:=Tmp; END;
X0:=X;
UNTIL Max<Epsilon;
END;
PROCEDURE Zeidel (n:Byte; A:MatrixType; B:VectorType; Epsilon:Real; VAR X:VectorType);
VAR i,k : Byte; s,Max,Tmp : Real;
BEGIN REPEAT Max:=0;
FOR i:=1 TO n DO BEGIN s:=B[i];
FOR k:=1 TO n DO s:=s-A[i,k]*X[k];
Tmp:=X[i]; X[i]:=X[i]+s/A[i,i];
Tmp:=Abs(X[i]-Tmp);
IF Max<Tmp THEN Max:=Tmp;
END;
UNTIL Max<Epsilon;
END;
CONST a : MatrixType = ( (110, 3, 4, -5, 16, 20), ( 1, 85, -6, 12, 11, -16), ( 24, -3, 54, -2, 0, 11),
( -8, 9, 0, 75, -9, 12), ( 0, 2, 3, -5, 98, 34), ( 16, 9, -4, -11, 0, 5));
b : VectorType = (100,200,300,400,500,600);
x0 : VectorType = (0,0,0,0,0,0);
CONST Eps = 1E-8;
VAR n,i,j : Byte; x : VectorType; d : Real;
BEGIN
n:=Nmax; x:=x0;
SimpleIteration(n,a,b,Eps,x);
WRITELN('Решение системы методом простой итерации и невязки:');
FOR i:=1 TO n DO BEGIN d:=b[i];
FOR j:=1 TO n DO d:=d-a[i,j]*x[j];
WRITELN(x[i]:12,' ',d:12); END;
x:=x0;
Zeidel(n,a,b,Eps,x);
WRITELN('Решение системы методом Зейделя и невязки :');
FOR i:=1 TO n DO BEGIN
d:=b[i]; FOR j:=1 TO n DO d:=d-a[i,j]*x[j];
WRITELN(x[i]:12,' ',d:12); END;
END.