Компьютерный форум OSzone.net  

Компьютерный форум OSzone.net (http://forum.oszone.net/index.php)
-   Программирование и базы данных (http://forum.oszone.net/forumdisplay.php?f=21)
-   -   [решено] Помогите с программой для Turbo Pascal (умножение матриц) (http://forum.oszone.net/showthread.php?t=187065)

dasha131 01-10-2010 13:45 1508885

Помогите с программой для Turbo Pascal (умножение матриц)
 
ПОмогите пожалуйста составить программу для вычисения произведения матриц A,B,C каждая из которых имеет размерность nxn

ВОт составленная мною часть проги, где вводятся сами матрицы, проверьте пожалуйста
program ABC;
var
matrA: array[1..500,1..500] of integer;
matrB: array[1..500,1..500] of integer;
matrC: array[1..500,1..500] of integer;
i: integer;
j: integer;

begin
for i:=1 to n do
for j:=1 to n do
begin
read matrA[i,j];
end;
begin
read matrB[i,j];
end;
begin
read matrC[i,j];
end;

Hector 01-10-2010 13:55 1508896

в принципе правильно, вот только нет ввода n и вместо оператора read лучше использовать readln imho, неплохо бы было выводить приглашение на ввод данных. размерность матриц лучше задавать через константу
Код:

const
R=500;
var
matrA: array[1..R,1..R] of integer;

ввод матриц я бы организовал процедурой
p. s. используйте тег CODE

dasha131 01-10-2010 14:02 1508902

Код:

program ABC;
var
const
R=500;
matr1,matr2,matr3,matr4: array[1..R,1..R] of real;
i,j,m,n,p,s,g: integer;
S:real;

Begin
  read (g)                    {размерность матрицы gxg}
  for i:=1 to g do
  for j:=1 to g do
        begin
        read(matr1[i,j]);
        end;
  for m:=1 to g do
  for n:=1 to g do
        begin
        read(matr2[m,n]);
        end;
  for p:=1 to g do
  for s:=1 to g do
        begin
        read(matr3[p,s]);
        end;


D[i,j] := D[i,j] + (A[i,j]*B[j,i])*C[j,i];
Вот формула

Значит матрицы мною заданны, как теперь задать их перемножение?

dasha131 01-10-2010 18:19 1509107

Сами матрицы точно правильно введутся?!

Hector 01-10-2010 18:38 1509127

Цитата:

Цитата dasha131
D[i,j] := D[i,j] + (A[i,j]*B[j,i])*C[j,i];
Вот формула »

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

dasha131 02-10-2010 04:57 1509427

Это не данная формула)) Значит моя ошибка(
МОжет поможете дальше с программой?

lxa85 02-10-2010 14:23 1509606

Цитата:

Цитата dasha131
блок const не надо смешивать с блоком var.
Код:

program ABC;
const
R=500;
var
matr1,matr2,matr3,matr4: array[1..R,1..R] of real;
i,j,m,n,p,s,g: integer;
S:real;
Begin
  read (g) {размерность матрицы gxg}
  for i:=1 to g do
  for j:=1 to g do
  begin
    read(matr1[i,j]);
  end;
  for m:=1 to g do
  for n:=1 to g do
  begin
    read(matr2[m,n]);
  end;
  for p:=1 to g do
  for s:=1 to g do
  begin
    read(matr3[p,s]);
  end;

»

Решение простое, "в лоб" можно конечно улучшить, но работать будет без проблем.
Цитата:

Цитата dasha131
Может поможете дальше с программой? »

Посмотри здесь
И вид общей формулы тут
Результирующую матрицу получать в 2 этапа. Сначала 1*2, затем получившее*3;
Процедуры и функции проходили? Они бы сейчас очень пригодились.

dasha131 02-10-2010 15:51 1509656

Код:

1.program AB;
2.const NMax = 10;{можно увеличить}
3.type Matrix = array [1..NMax, 1..NMax] of Real; 
 
4.procedure MulMatrix(var a, b, c: Matrix; n: Integer);
5.var  i, j, k: Integer;
6.  s: Real;
7.begin
8.    for i := 1 to n do
9.    for j := 1 to n do
10.    begin
11.        s := 0;
12.          for k := 1 to n do
13.          s := s + a[i, k]*b[k, j];
14.          c[i, j] := s
15.    end
 
16.end;
 
17.var  a, b, c: Matrix;
18.    i, j, n: Integer;
19.begin
20.    WriteLn('Введите порядок матрицы');
21.    Write('n = '); ReadLn(n);
 
22.    WriteLn('Введите первую матрицу');
23.    for i := 1 to n do
24.    for j := 1 to n do
25.    Read(a[i, j]);
 
26.    WriteLn('Введите вторую матрицу');
27.    for i := 1 to n do
28.    for j := 1 to n do
29.    Read(b[i, j]);
 
30.    MulMatrix(a, b, c, n);
 
31.    for i := 1 to n do
32.    begin
33.          for j := 1 to n do
34.          Write(c[i, j]:0:6, ' ');
35.          WriteLn
36.    end;
37.    ReadLn
38.end.

Благодарю за помощь) А можно по подробнее разобрать цикл с 4-15строчки, почему вконце 14 и 15й строчек не ставится ";" ? Почему так записали 31-33ю строчки, почему begin между? И еще непонятно значение строчек 35,37...

Hector 03-10-2010 19:55 1510483

Цитата:

Цитата dasha131
Почему так записали 31-33ю строчки, почему begin между? »

это вывод матрицы, внешний цикл выбирает номер строки, а в его теле внутренний выводит значение элементов, а пустой writeln переводит каретку (чтоб красиво было :) )
Цитата:

Цитата dasha131
И еще непонятно значение строчек 35,37 »

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

Цитата dasha131
почему вконце 14 и 15й строчек не ставится ";" ? »

код тестировали? imho просто ошибка, забыли поставить
Цитата:

Цитата dasha131
разобрать цикл с 4-15строчки »

это реализация математического метода умножения матриц

dasha131 04-10-2010 07:30 1510853

Цитата:

Цитата Hector
код тестировали? imho просто ошибка, забыли поставить »

ВОт это то самое и интересное, все тестировалось, и работало прекрасно без ";" ну и как это объяснить?

А чтобы перемножать три матрицы, нужно новый цикл писать "MulMatrix(var c, d, e: Matrix; n: Integer)" ??

dasha131 04-10-2010 07:54 1510865

Вот готово, замечания будут?
Код:

program ABC;
const NMax = 10;
type Matrix = array [1..NMax, 1..NMax] of Real; 
 
procedure 1MulMatrix(var a, b, c: Matrix; n: Integer);
var  i, j, k: Integer;
    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;
procedure 2MulMatrix(var c, d, e: Matrix; n: Integer);
var  i, j, k: Integer;
    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 + c[i, k]*d[k, j];
          e[i, j] := s
    end
 
end;
 
var  a, b, c,d,e: Matrix;
    i, j, n: Integer;
begin
    WriteLn('vvedite poradok matrix');
    Write('n = '); ReadLn(n);
 
    WriteLn('vvedite pervyu');
    for i := 1 to n do
    for j := 1 to n do
    Read(a[i, j]);
 
    WriteLn('vvedite vtoryu');
    for i := 1 to n do
    for j := 1 to n do
    Read(b[i, j]);
 
 WriteLn('vvedite tretu');
    for i := 1 to n do
    for j := 1 to n do
    Read(d[i, j]);

    MulMatrix(a, b, c, n);
    MulMatrix(c, d, e, n);
 
    for i := 1 to n do
 begin
          for j := 1 to n do
          Write(e[i, j]:0:6, ' ');
          WriteLn
    end;
    ReadLn
end.


lxa85 04-10-2010 11:02 1510963

Цитата:

Цитата dasha131
Вот готово, замечания будут? »

Будут :)
Код:

program ABC;
const NMax = 10;
type Matrix = array [1..NMax, 1..NMax] of Real; 
 
procedure MulMatrix(var M1, M2, M3: Matrix; n: Integer);
var  i, j, k: Integer;
    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 + M1[i, k]*M2[k, j];
          M3[i, j] := s
    end
 
end;

procedure VvodM(var M1:Matrix; n:integer);
var
    i,j:integer;
begin
    for i := 1 to n do
    for j := 1 to n do
        Read(M1[i, j]);
end;

procedure VivodM(var M1:Matrix; n:integer);
var
    i,j:integer;
begin
    for i := 1 to n do
    begin
          for j := 1 to n do
              Write(M1[i, j]:0:6, ' ');
          WriteLn;
    end;
end;


var  a, b, c,d,e: Matrix;
    i, j, n: Integer;
begin
    WriteLn('vvedite poradok matrix');
    Write('n = '); ReadLn(n);
 
    WriteLn('vvedite pervyu');
    VvodM(a, n);
    WriteLn('vvedite vtoryu');
    VvodM(b, n);
    WriteLn('vvedite tretu');
    VvodM(c, n);

    MulMatrix(a, b, d, n);
    MulMatrix(c, d, e, n);
 
    VivodM(e,n);

    ReadLn;
end.

Как вариант, можно кусочек переписать иначе, через функцию:

Код:

finction MulMatrix(var M1, M2; n: Integer):Matrix;
var  i, j, k: Integer;
    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 + M1[i, k]*M2[k, j];
          result[i, j] := s
    end
end;

соотв. в основном теле программы будет:

Код:

d:=MulMatrix(a,b,n);
e:=MulMatrix(c,d,n);

Общие комментарии:
Вообще не стОит путать локальные(внутри процедур и функций) и глобальные(общие для всей программы) переменные.
Поэтому я переименовал в процедурах a, b, c, e и т.д. в более условные и единые M1, M2, M3.
i, j, k счетчики, с ними все ясно.
Массивы a, b, c - основные.
d, e производные от умножения.
Бывшие процедуры 1MulMatrix, 2MulMatrix нигде не вызывались, соотв. заменены на вызываемую MulMatrix с разными передаваемыми ей аргументами.
Конечный Readln; по большому счету не нужен. Он служит для паузы во время отладки. При финальной компиляции программы эту строчку желательно закоментировать.

dasha131 13-10-2010 14:55 1517958

Спасибо, да действительно объединение двух процедур перемножения в одну очень кстати, и процедура ввода весьма удобна, а вот процедура вывода кажется мне лишней=)

dasha131 13-10-2010 15:18 1517976

Проверила все в ручную на примере перемножения матриц размерностью 3х3 в первой программа все вычисляется верно, а во второй где процедуры объединены неверно, почему так??

lxa85 13-10-2010 15:23 1517981

dasha131, приведи код программы пожалуйста. В которой процедуры объединены и работают не верно.

dasha131 14-10-2010 12:50 1518634

Вот же он.
Выше вами приведенный

Да вот кстати обьясните пожалуйста почему в моём варианте кода выбор параметра в процедуре по ссылке лучше чем по значению???

dasha131 15-10-2010 18:01 1519635

lxa85,
Цитата:

Цитата lxa85
приведи код программы пожалуйста »

Я имею веду ваш код!

lxa85 15-10-2010 18:12 1519642

Странно, вроде бы ошибки быть не должно.
Давай сравнивать входные наборы и полученные результаты.

Цитата:

Цитата dasha131
Да вот кстати обьясните пожалуйста почему в моём варианте кода выбор параметра в процедуре по ссылке лучше чем по значению?? »

Ты имеешь в виду в чем отличие записи
procedure VvodM(var M1:Matrix; n:integer); от
procedure VvodM(M1:Matrix; n:integer);
При вызове процедуры (функции) выделяется память, в нее записываются передаваемые данные и служебная информация.
Передавать ссылку на массив проще, нежели сам массив. Это быстрее, экономичнее в плане ресурсов и времени.
Если этого не делать, а передавать в процедуру весь массив, то при большой "вложенности" процедур с пересылками полного массива данных, может возникнуть переполнение доступной памяти. Если передавать ссылки, этого не произойдет. Однако следует быть внимательным к тому, что на что и когда ссылается.

Для наглядности предложу вариант с книжной библиотекой. Если понадобилась информация, нас адресуют к нужному стеллажу. Перетаскивать к себе домой 6 рядов книг, чтобы прочесть эпиграф к произведению - нецелесообразно. Можно конечно, но не нужно :)

dasha131 15-10-2010 18:26 1519650

Понятно обьяснили, спасибо!=)

dasha131 15-10-2010 18:45 1519669

результат получается числа но не те
ввожу матрицы, пеемножение которых было проверенно мной в ручную
размерность=3
3 2 1 0 4 7 7 4 0
4 0 5 8 2 1 8 2 1
7 0 2 6 5 0 9 1 1

правильный ответ
529 153 44
790 230 69
829 173 87

ответ выдаваемый программой
274 311 273
248 288 289
240 268 284

Попробовала убрать вызов второй процедуры и вывисти результат перемножения AB, результат сошолся с тем который был получен в ручную
22 21 23
30 41 28
12 38 49

dasha131 15-10-2010 19:21 1519686

Ну все, причина найдена

MulMatrix(a, b, d, n); d:=MulMatrix(a,b,d,n);
MulMatrix(d, c, e, n); e:=MulMatrix(c,d,e,n);

у нас он вы чиcлял как C*AB , а в планах было AB*C
хоты разницы особой нет, по свойству матриц A*B=B*A но все же лучше будет записать
MulMatrix(a, b, d, n);
MulMatrix(d, c, e, n);
Все правильно?=)

lxa85 15-10-2010 19:42 1519696

Цитата:

Цитата dasha131
Все правильно? »

Да. Но A*B не равно B*A.
От сюда была ошибка, и я рад, что ты нашла ее первой :)


Время: 06:46.

Время: 06:46.
© OSzone.net 2001-