[C++] mnożenie macierzy

Sidu
Użytkownik
Użytkownik
Posty: 86
Rejestracja: 16 mar 2011, o 11:27
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 8 razy

[C++] mnożenie macierzy

Post autor: Sidu »

Witam,

na studiach właśnie zaczął mi się C++. Oczywiście uczenie na studiach takich rzeczy zaczyna się z grubej rury i ciężko jest cokolwiek samemu ogarnąć z wykładu. Na ćwiczeniach doktor dał za zadanie, żeby wykonać mnożenie dwóch macierzy. Znalazłem tu na forum taki program:
https://www.matematyka.pl/56375.htm

Troche go zmieniłem, dodając losowe generowanie macierzy. Mniej więcej wszystko ogarnąłem, tylko jedno jest dla mnie niezrozumiałe. Pewnie jest to cała istota tego programu Chodzi o te funkcje for co jest na początku programu mnozeniemacierzy. Co tam się dokładnie dzieje, jakby ktoś mógł mi wytłumaczyć każdą linijke. Wydaje mi się, że for użyte niżej gdzie jest też printf użyte, sprawia, że bierze po kolei każdą rubryke macierzy i wpisuje tam cyfre.

Kod: Zaznacz cały

#include <stdio.h>
#include <cstdlib>
#include <iostream>
#include <ctime>
#define ILWIERSZY 2
#define ILKOLUMN 3



/* Mnozenie macierzy A * B = C */
int mnozeniemac(double A[ILWIERSZY][ILKOLUMN], double D[ILKOLUMN][ILWIERSZY], double C[ILWIERSZY][ILKOLUMN]) {
  int i, j, k;
  for(i = 0; i < ILWIERSZY; i++)
    for(j = 0; j < ILKOLUMN; j++)
      C[i][j] = 0;
  for(i = 0; i < ILWIERSZY; i++)
    for(j = 0; j < ILWIERSZY; j++)
      for(k = 0; k < ILKOLUMN; k++)
        C[i][j] = C[i][j] + A[i][k] * D[k][j];
  return 0;
}


int main() {
  int i, j;  // liczniki
  srand( time( NULL ) );
  double A[2][3] = {
    {rand() % 11,rand() % 11, rand() % 11}, 
    {rand() % 11, rand() % 11, rand() % 11}};
  double B[2][3] = {
    {rand() % 11,rand() % 11, rand() % 11}, 
    {rand() % 11, rand() % 11, rand() % 11}};
  double C[2][3]; // macierz wyników
  double D[3][2] = {
    {rand() % 11, rand() % 11}, 
    {rand() % 11, rand() % 11},
    {rand() % 11, rand() % 11}};
  
  printf("Macierz A
");
  for(i = 0; i < ILWIERSZY; i++) 
  {
    for(j = 0; j < ILKOLUMN; j++)
      printf("%g ", A[i][j] );
   puts("");
  }
  puts("");
  
  
  printf("Macierz D
");
  for(i = 0; i < ILKOLUMN; i++) {
    for(j = 0; j < ILWIERSZY; j++)
      printf("%g ", D[i][j] );
    puts("");
  }
  puts("");
  
  mnozeniemac(A, D, C);
  printf("Iloczyn macierzy A * D
");
  for(i = 0; i < ILWIERSZY; i++) {
    for(j = 0; j < ILWIERSZY; j++)
      printf("%g ", C[i][j] );
    puts("");
  }

  return 0;
}


Jeszcze pytanie na koniec. Czy da się to napisać krócej lub prościej... bardziej amatorsko
Ponury123
Użytkownik
Użytkownik
Posty: 128
Rejestracja: 5 lip 2015, o 14:48
Płeć: Mężczyzna
Lokalizacja: nie wiem
Podziękował: 11 razy
Pomógł: 24 razy

[C++] mnożenie macierzy

Post autor: Ponury123 »

pytanie pierwsze czy wiesz jak w ogólnie działa pętla for i pytasz tylko konkretnie o to co się dzieję w tym programie czy może po prostu nie wiesz jak działa for?

Co do tego fora z printf to trochę pudło bo ten for wypisuje w konsoli kolejne wartości z tablicy C - która jest dwuwymiarowa.

Natomiast to w tej pętli for co jest na początku
Chodzi o te funkcje for co jest na początku programu mnozeniemacierzy.
tam właśnie są jakieś wartości wrzucane do kolejnych kolumn i wierszy tablic
np.

Kod: Zaznacz cały

int i, j, k;
  for(i = 0; i < ILWIERSZY; i++)
    for(j = 0; j < ILKOLUMN; j++)
      C[i][j] = 0;
tutaj do każdej komórki tablicy(macierzy) są wpisywane zera.
Sidu
Użytkownik
Użytkownik
Posty: 86
Rejestracja: 16 mar 2011, o 11:27
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 8 razy

[C++] mnożenie macierzy

Post autor: Sidu »

no ok, ale czemu

Kod: Zaznacz cały

C[i][j] = 0;
i czemu

Kod: Zaznacz cały

C[i][j] = C[i][j] + A[i][k] * D[k][j];
wiem, że to C jest potrzebne w tym równaniu, bo wtedy wychodzi zły wynik... ale czemu
Mruczek
Użytkownik
Użytkownik
Posty: 1114
Rejestracja: 26 paź 2008, o 19:43
Płeć: Mężczyzna
Podziękował: 23 razy
Pomógł: 157 razy

[C++] mnożenie macierzy

Post autor: Mruczek »

Pytanie zasadnicze: czy Ty wiesz co robisz? Czy wiesz co to jest mnożenie macierzy i jak zrobić to na kartce? Jeżeli tak, to nie zadawałbyś takich pytań.

Na początku trzeba wyzerować komórki wynikowej tablicy - to robi to pierwsze.
Potem każda komórka jest wyliczana oddzielnie jako suma iloczynów komórek wiersza macierzy A i kolumny macierzy D, a to wyrażenie na dole dodaje iloczyn dwóch komórek do wyniku komórki.
No jaśniej już się chyba nie da.
Ponury123
Użytkownik
Użytkownik
Posty: 128
Rejestracja: 5 lip 2015, o 14:48
Płeć: Mężczyzna
Lokalizacja: nie wiem
Podziękował: 11 razy
Pomógł: 24 razy

[C++] mnożenie macierzy

Post autor: Ponury123 »

Spróbuje jaśniej, może się uda

Kod: Zaznacz cały

C[i][j] = 0;
robimy dlatego że

Kod: Zaznacz cały

C[i][j] = C[i][j] + A[i][k] * D[k][j];
uprośćmy to do postaci

Kod: Zaznacz cały

C=C+A*D
czyli wartość \(\displaystyle{ C}\) staję się wartością \(\displaystyle{ C + A \cdot D}\), i chodzi o to co jest w tym \(\displaystyle{ C}\) na samym początku
bo jak mamy
\(\displaystyle{ C=0, A=2, D=3,}\)
to wynik jest oczywisty \(\displaystyle{ C = 0 + 2 \cdot 3}\) czyli \(\displaystyle{ C=6}\)
jakbyśmy drugi raz zrobili to samo to mamy \(\displaystyle{ C = 6 + 2 \cdot 3}\) czyli \(\displaystyle{ C=12}\)

Ale jak w C nie ma 0 bo tego nie przypisaliśmy to jest tam (powiedzmy) NULL, a NULL + 6 to wcale nie jest 6

zamień sobie ten fragment

Kod: Zaznacz cały

  double A[2][3] = {
    {rand() % 11,rand() % 11, rand() % 11}, 
    {rand() % 11, rand() % 11, rand() % 11}};
na

Kod: Zaznacz cały

  double A[2][3];
i odpal program, zobaczysz co się wtedy znajduje w komórkach tablicy A.
Nie wiem czy jasniej, ale próbowałem ;p
Sidu
Użytkownik
Użytkownik
Posty: 86
Rejestracja: 16 mar 2011, o 11:27
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 8 razy

[C++] mnożenie macierzy

Post autor: Sidu »

Ponury, zrobiłem tak i wyskoczyło mi

Kod: Zaznacz cały

4.94066e-324 2.10265e-317 0
1.133e-317 1.59741e-317 4.3437e-311
i mało mi to mówi.

rozpisałem sobie na kartce to równanie i już wiem, ale nadal nie rozumiem działania teog co się dzieje w funkcji for.

Gdyby tylko mi działał debug w dev-c++...
kalwi
Użytkownik
Użytkownik
Posty: 1931
Rejestracja: 29 maja 2009, o 11:58
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 145 razy
Pomógł: 320 razy

[C++] mnożenie macierzy

Post autor: kalwi »

Można wiedzieć, skąd pomysł o korzystaniu z dev-c++?

Poza tym wszystko to, co napisałeś tak naprawdę jest równe 0, ale taka postać wynika z użycia typu double.
Ponury123
Użytkownik
Użytkownik
Posty: 128
Rejestracja: 5 lip 2015, o 14:48
Płeć: Mężczyzna
Lokalizacja: nie wiem
Podziękował: 11 razy
Pomógł: 24 razy

[C++] mnożenie macierzy

Post autor: Ponury123 »

Sidu,

no własnie o to chodzi, jeśli ty nie przypiszesz wartości do poszczególnych komórek tablicy(dajmy na to tego zera o które się rozchodzi) to komputer zrobi to sam i powrzuca tam jakieś takie liczby

Kod: Zaznacz cały

4.94066e-324 2.10265e-317 0
1.133e-317 1.59741e-317 4.3437e-311
więc jak do tych liczb dodasz wynik mnożenia macierzy to też Ci wyjdą jakieś dziwne liczby,
dlatego do tablicy C przypisujesz same zera bo zero plus wynik mnożenia macierzy to masz w C wynik mnożenia macierzy.

PS. kalwi ma rację co do tego że te liczby co Ci wypisało to zero tyle że zapisane tak bo typ. Po prostu "dziwne liczby" wydały mi się łatwiejsze do wytłumaczenia.
Sidu
Użytkownik
Użytkownik
Posty: 86
Rejestracja: 16 mar 2011, o 11:27
Płeć: Mężczyzna
Lokalizacja: Warszawa
Podziękował: 8 razy

[C++] mnożenie macierzy

Post autor: Sidu »

kalwi pisze:Można wiedzieć, skąd pomysł o korzystaniu z dev-c++?

Poza tym wszystko to, co napisałeś tak naprawdę jest równe 0, ale taka postać wynika z użycia typu double.

na laboratoriach pracuje w c++ builderze co jest jeszcze gorsze.

czyli to na początku poprzez define ustalam te ilość wierszy i kolumn i tworze 3 takie same macierze wypełnione zerami. Potem przekształcam macierz C żeby wymiar był odpowiedni.
ODPOWIEDZ