Помощь - Поиск - Пользователи - Календарь
Полная версия: умножение кв. матриц
Форум «Всё о Паскале» > Pascal, Object Pascal > Задачи
Insomnia
Условие и состоит в том что бы перемножить 2 квадратные матрицы
program ymnoz_matr_on_matr;

{$APPTYPE CONSOLE}

uses
SysUtils,
windows;

const
n=3;
m=3;
r=3;
type
TElem=integer;
TMatrixA=array [1..n,1..n] of TElem;
TMAtrixB=array[1..m,1..m] of TElem;
TMatrixC=array[1..r,1..r] of TElem;
var
A: TMatrixA;
B: TMAtrixB;
C: TMAtrixC;

procedure input_matrixs (var A: TMatrixA;n: TElem;var B: TMAtrixB;m: TElem);
var i,j,k,l: integer;
begin
writeln('введите матрицу А');
for i:=1 to n do
begin
for j:=1 to n do
read(A[i,j]);
readln
end;
writeln('введите матрицу B');
for k:=1 to m do
begin
for l:=1 to m do
read(B[k,l]);
readln
end;
end;

procedure Ym_matr_on_matr(A: TMatrixA;B: TMatrixB;var C: TMatrixC;r: TElem);// умножение матриц
var p,f: integer;
//---------
function Scalar_Vector_A_on_Vector_B (Row,Col: integer): TElem;//умножение строки Row матрицы А и столбца Col матрицы B
var i,j: integer;
begin
result:=0;
i:=0;
for j:=1 to n do
inc(i);
result:=A[Row,j]*B[i,Col]+result;
end;

begin
for p:=1 to r do
begin
for f:=1 to r do
C[p,f]:= Ym_matr_on_matr(i,j);
end;

procedure print_matrixC (C: TMatrixC;r: TElem);
var
p,f: integer;
begin
writeln('матрица С');
for p:=1 to r do
begin
for f:=1 to r do
write(C[p,f],' ');
writeln
end;
end;

begin
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
input_matrixs(A,n,B,m);
Ym_matr_on_matr(A,B,C,r);
print_matrixC(C,r);
readln
end.


запутался в функции (и процедуре). Идея в том что бы умножить 1 строку и 1 столбец матриц , а потом создать цикл обхода по двум матрицам и использовать вспомогательную функцию.
DarkWishmaster
Цитата(Insomnia @ 6.06.2011 20:57) *

Условие и состоит в том что бы перемножить 2 квадратные матрицы
запутался в функции (и процедуре). Идея в том что бы умножить 1 строку и 1 столбец матриц , а потом создать цикл обхода по двум матрицам и использовать вспомогательную функцию.

не понимаю зачем использовать 3 константы с одними и тем же значениями? зачем создать тип интегер если он уже существует?
вот умножение двух квадратных матриц:

Uses Crt;
const Nmax=10; //ранг матрицы не больше 10
type matrice=array[1..Nmax,1..Nmax] of integer;
var a,c,b:matrice; i,j:byte; N:1..Nmax;
procedure Multiply(var a,b:matrice);
var i,j,k:byte;
begin
for i:=1 to N do
for j:=1 to N do
for k:=1 to N do
C[i,j]:=C[i,j]+a[i,k]*b[k,j]; //умножаем
end;
procedure Print(var a:matrice); //выводим на экран
var i,j:byte;
begin
for i:=1 to N do
begin
for j:=1 to N do
write(a[i,j],' ');
writeln;
end;
end;
Begin ClrScr;
readln(N);
writeln('A');
for i:=1 to N do
for j:=1 to N do
readln(a[i,j]);
writeln('B');
for i:=1 to N do
for j:=1 to N do
readln(b[i,j]);
Multiply(a,b);
Print©;
readln;
end.


IUnknown
Цитата
Условие и состоит в том что бы перемножить 2 квадратные матрицы
, тогда ты сам себя запутал:

Цитата
const
n=3;
m=3;
r=3;
type
TElem=integer;
TMatrixA=array [1..n,1..n] of TElem;
TMAtrixB=array[1..m,1..m] of TElem;
TMatrixC=array[1..r,1..r] of TElem;
var
A: TMatrixA;
B: TMAtrixB;
C: TMAtrixC;

Это все ни к чему. Квадратные матрицы могут быть перемножены только тогда, когда имеют одинаковый размер, поскольку для перемножения матриц нужно, чтоб количество столбцов первой равнялось количеству строк второй. Если будут квадратные матрицы разного размера - их произведения не существует.

Описывай нормально:
const
n = 3;
type
TElem = integer;
TMatrix = array[1 .. n, 1 .. n] of TElem;
var
A, B, C : TMatrix;
Ну, а сама процедура - вот так:

procedure Mult(A, B : TMatrix; var C : TMatrix);

function ScalarVecA_VecB (RowA, ColB : integer) : TElem;
var i : integer;
begin
result := 0;
for i := 1 to n do
result := result + A[RowA, i] * B[i, ColB];
end;

var
i, j : integer;

begin
for i := 1 to n do
for j := 1 to n do
C[i, j] := ScalarVecA_VecB(i, j);
end;
, хотя вот тут: Массивы. Матрицы. Типичные задачи. Олег выкладывал перемножение квадратных, а я - "сцепленных" матриц... Можно было бы и воспользоваться...

Добавлено через 1 мин.
Цитата
зачем создать тип интегер если он уже существует?
Затем, чтобы потом одним движением перейти к работе с вещественной матрицей. Ага? Или с комплексной... Или с любой другой. Меняешь тип, и все, больше ничего менять не надо... В крайнем случае - перегрузить операторы сложения/умножения...

Update:

Цитата
не понимаю зачем использовать 3 константы с одними и тем же значениями? зачем создать тип интегер если он уже существует?
А я не понимаю, зачем
1) передавать в процедуру матрицы как Var-параметры, когда они не должны меняться. Специально, чтоб была возможность ошибиться и изменить значение? Не надо. Есть передача по значению, без Var. Если матрицы большие - то можно передать по константной ссылке : Procedure Mult(const A, B : TMatrix). В первом случае даже случайное изменение матрицы не передастся наружу. А во втором это вообще будет невозможно. Компилятор даст по рукам за каждую попытку присвоить какое-то значение константному параметру;

2) использовать глобальные переменные для возвращения результата. Что, очень нравится писать подпрограммы с побочными эффектами? Эта привычка может сослужить плохую службу. Чем меньше подпрограмма влияет на "внешнюю среду" - тем лучше. В идеале она должна общаться с "внешним миром" только через параметры;

3) переменные, описанные локально, описывать также и глобально. Все равно они не используются, преимущество среди всех одноименных переменных - у наиболее вложенной.

4) описывать переменные, которые тебе нужны потом, сразу в начале программы. Чем меньше времени живет переменная (и чем меньше других о ней знают) - тем лучше. Меньше соблазна где-нибудь случайно изменить значение и потом сидеть и искать ошибку. Описывай переменные КАК МОЖНО НИЖЕ по тексту.
Insomnia
точно. я себе всего много накрутил. почистил, все работает. Правда я никак не могу представить, функция у нас возвращает строку и столбец, которые мы в процедуре заполняем, пробегая по циклу матрицы С, верно? получается что result хранит большое выражение ( " A [RowA, 1] * B [1, ColB] + A [RowA, 2]* B [2, ColB] + A [RowA, 3] * B [3, ColB] ; для i = 1 " ) . А непосредственно в процедуре прогоняя i и j , которые подставляются в RowA и ColB, заполняем матрицу С .

P.S. большое спасибо за помощь
IUnknown
Цитата
Правда я никак не могу представить, функция у нас возвращает строку и столбец, которые мы в процедуре заполняем, пробегая по циклу матрицы С, верно? получается что result хранит большое выражение ( " A [RowA, 1] * B [1, ColB] + A [RowA, 2]* B [2, ColB] + A [RowA, 3] * B [3, ColB] ; для i = 1 " )
Нет. Функция возвращает число (оно и из названия понятно: скалярное произведение вектора A на вектор B) - результат умножения строки RowA матрицы A на столбец RowB матрицы B. Чтобы вычислить матрицу- результат, надо КАЖДУЮ строку A умножить на КАЖДЫЙ столбец B, чем и занимается сама процедура. Что называется, "разделяй и властвуй". Задача была разбита на подзадачи. Вместо того, чтобы делать три вложенных цикла, ограничились двумя, перебирающими все нужные комбинации векторов. И функцией, которая самостоятельно выполняет третий цикл, перемножая два конкретных вектора.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.