Версия для печати темы

Нажмите сюда для просмотра этой темы в обычном формате

Форум «Всё о Паскале» _ Задачи _ Обратная матрица

Автор: Pasha 3.06.2005 23:42

Собственно требуется найти матрицу обратную данной! (способ нахождения не принципиален)
Нужно ввести размерность квадратной матрицы (мах 10*10), затем ручками ввести её, и вывести на экран результат..


Думал по зубам прога, а оказалось что зубов вовсе нету sad.gif Подскажите пожалуйста .. в понедельник сдавать уже.

Автор: volvo 3.06.2005 23:54

Ну, раз способ не принципиален, то попробуй скачать модуль, который я выкладывал здесь: http://forum.pascal.net.ru/index.php?showtopic=2694&view=findpost&p=28387, там обрати внимание на функции matrixInvert (для инвертирования) и mxInput (для ввода матрицы)

Автор: Guest 4.06.2005 1:26

Под словами "(способ нахождения не принципиален)" я имелл ввиду алгебраический способ.
А вот на паскале мне нужно что бы всё было без модулей! ! ! там всякие процедуры и функции можно...

честно говоря я что то не разобрался как воспользоватся твоим модулем...

Автор: Altair 4.06.2005 1:34

{
НАХОЖДЕНИЕ ОБРАТНОЙ МАТРИЦЫ

Используется псевдо-метод Гаусса.
Если к матрице приписать справа единичную матрицу, а затем с
помощью линейных преобразований привести левую матрицу к единичной,
проводя те же преобразования над правой (изначально единичной)
матрицей, то на ее месте образуется матрица, обратная к исходной.
К линейным преобразованиям относятся прибавление одной строки,
умноженной на произвольный коэффициент, к другой. Решение можно
разбить на два этапа: "прямой" и "обратный" ход.
Есть исходная матрица, приписываем к ней единичную:
а[1,1], а[1,2], ..., а[1,n]; 1, 0, ..., 0;
а[2,1], а[2,2], ..., а[2,n]; 0, 1, ..., 0;
...
а[n,1], а[n,2], ..., а[n,n]; 0, 0, ..., 1;
Во время "прямого" хода необходимо добиться нулей под главной
диаганалью левой матрицы. Берем первую строку и делим ее на а[1,1].
Теперь на месте а[1,1] стоит 1. Вычитаем из второй строки первую
умноженную на а[2,1] - на месте этого элемента появляется ноль.
Аналогично для всех строк до n-ой.
Теперь в первом столбце матрицы ниже единицы стоят нули.
Переходим ко второй строке и для всех строк ниже второй повторям
описанную процедуру. Теперь ниже диагонали и во второй строке нули.
Так продолжаем до (n-1)-ой строки. Для n-ной строки достаточно
разделить ее на а[n,n].
Матрица а приведена к верхней треугольной. На месте единичной обр
азовалась некая матрица.
!! Если на месте диагонального элемента левой матрицы образуется число
близкое к нулю, то деление на малое число приведет к значительной
погрешности вычисления. Поэтому необходимо, чтобы это число было "далеко"
от нуля. С этой целью предпринимается следующий шаг: перед тем, как
разделить строку на этот элемент, прибавим к строке все нижележащие
строки (умноженные на -1 если в этом столбце стоит отрицательный элемент).
Обратный ход. Здесь сначала добвиваемся нулей в последнем столбце
матрицы а. Для этого из каждой строки (i) выше n-ной вычитаем n-ную
умноженную на а[i,n]. Затем добиваемся нулей в (n-1)-ом столбце и так
далее до второго столбца.
Теперь слева имеем единичную матрицу, а справа, на месте единичной -
искомая обратная матрица. Для проверки перемножим ее на начальную -
олжна получиться единичная.
}
const
n=3;
eps=0.000000001; { all numbers less than eps are equal 0 }
type matr=array[1..n,1..n] of real;
var
a,b,a0:matr;
i,j,imx,np:integer;
s0,s1:real;
procedure PrintMatr(m,m1:matr;n,nz,nd:integer);
var
i,j:integer;
begin
for i:=1 to n do
begin
if (i=1) then write(np:2,':') else write(' ');
for j:=1 to n do write(m[i,j]:nz:nd);
for j:=1 to n do write(m1[i,j]:nz:nd);
writeln;
end;
inc(np);
end;

procedure MultString(var a,b:matr;i1:integer;r:real);
var
j:integer;
begin
for j:=1 to n do
begin
a[i1,j]:=a[i1,j]*r;
b[i1,j]:=b[i1,j]*r;
end;
end;

procedure AddStrings(var a,b:matr;i1,i2:integer;r:real);
{ Процедура прибавляет к i1 строке матрицы a i2-ю умноженную на r}
var
j:integer;
begin
for j:=1 to n do
begin
a[i1,j]:=a[i1,j]+r*a[i2,j];
b[i1,j]:=b[i1,j]+r*b[i2,j];
end;
end;

procedure MultMatr(a,b:matr;var c:matr);
var
i,j,k:byte;
s:real;
begin
for i:=1 to n do
for j:=1 to n do
begin
s:=0;
for k:=1 to n do s:=s+a[i,k]*b[k,j];
c[i,j]:=s;
end;
end;

function sign(r:real):shortint;
begin
if (r>=0) then sign:=1 else sign:=-1;
end;


{MAIN}
begin
randomize;
for i:=1 to n do
begin
for j:=1 to n do
begin
b[i,j]:=0;
a[i,j]:=1.0*random(8)-4;
end;
b[i,i]:=1;
end;
{ отладочные присвоения}
a[1,1]:= 1; a[1,2]:=-1; a[1,3]:= 2; {a[1,4]:= 0;}
a[2,1]:= 0; a[2,2]:=-2; a[2,3]:= 3; {a[2,4]:= 5;}
a[3,1]:= 0; a[3,2]:=-1; a[3,3]:= 1; {a[3,4]:= 2;
a[4,1]:= 0; a[4,2]:=-2; a[4,3]:= 3; a[4,4]:=-4;

a[1,1]:= 5; a[1,2]:= 7; a[1,3]:= 7; a[1,4]:= 1;
a[2,1]:= 6; a[2,2]:= 6; a[2,3]:= 3; a[2,4]:= 4;
a[3,1]:= 5; a[3,2]:= 1; a[3,3]:= 1; a[3,4]:= 1;
a[4,1]:= 3; a[4,2]:= 3; a[4,3]:= 3; a[4,4]:= 3;
}
for i:=1 to n do
for j:=1 to n do a0[i,j]:=a[i,j];
writeln('Starting matrix:'); np:=0;
PrintMatr(a,b,n,6,1);
for i:=1 to n do
begin
for j:=i+1 to n do AddStrings(a,b,i,j,sign(a[i,i])*sign(a[j,i]));
{ PrintMatr(a,b,n,6,1);}
if (abs(a[i,i])>eps) then
begin
MultString(a,b,i,1/a[i,i]);
for j:=i+1 to n do AddStrings(a,b,j,i,-a[j,i]);
{ PrintMatr(a,b,n,6,1);}
end else
begin
writeln('Обратной матрицы не существует.');
halt;
end
end;
{writeln('Обратный ход:');}
if (a[n,n]>eps) then
begin
for i:=n downto 1 do for j:=1 to i-1 do
begin
AddStrings(a,b,j,i,-a[j,i]);
end;
{ PrintMatr(a,b,n,8,4);}
end else writeln('Обратной матрицы не существует.');
MultMatr(a0,b,a);
writeln('Начальная матрица, обратная к ней матрица:');
PrintMatr(a0,b,n,7,3);
writeln('Проверка: должна быть единичная матрица.');
PrintMatr(a,a,n,7,3);
end.


Автор: Guest 4.06.2005 2:02

www.pscal.al.ru ;)
Это конечно круто НО! этим я уже пользовался smile.gif
Да и потом тут используется автозаполнение случайными числами а мне нужно что бы я сам вводил матрицу ...

Автор: volvo 4.06.2005 3:26

Цитата(Guest @ 3.06.05 22:02)
Это конечно круто НО! этим я уже пользовался smile.gif

А что, у нас тут есть телепаты, чтобы знать, кто чем пользовался, а кто-нет?
Вот я немного изменил свою программу из FAQ-а (только учти, обработки ошибок нет, чуть что - программа вылетит):


Прикрепленные файлы
Прикрепленный файл  INVERT.PAS ( 3.73 килобайт ) Кол-во скачиваний: 1125

Автор: Altair 4.06.2005 18:07

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

А переписать пару строчек для ручного ввода слабо?

Цитата
www.pscal.al.ru
Это конечно круто НО! этим я уже пользовался

Дело бы пошло гораздо быстрее, если бы ты сразу сказал что пользовался этим и что тебе не подошло здесь, проще что-то дописать или изменить ...