Помощь - Поиск - Пользователи - Календарь
Полная версия: умножение кв. матриц
Форум «Всё о Паскале» > 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(c);
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, чем и занимается сама процедура. Что называется, "разделяй и властвуй". Задача была разбита на подзадачи. Вместо того, чтобы делать три вложенных цикла, ограничились двумя, перебирающими все нужные комбинации векторов. И функцией, которая самостоятельно выполняет третий цикл, перемножая два конкретных вектора.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.