Matrixmultiplikation
-
Hallo,
ich wollte einmal testen, wie man programmtechnische eine Matrixmultiplikation umsetzen will. Dazu habe ich mir folgendes Testprogramm geschrieben:
# include <stdio.h> # include <stdlib.h> # include <math.h> int main() { double *F, *G, *A; int i, j, m, n; printf("Eingabe der Zeilenanzahl: "); scanf("%d", &m); printf("Eingabe der Spaltenanzahl: "); scanf("%d", &n); F = (double *) malloc (m*n*sizeof(double)); for ( i = 0; i < m; ++i) { for ( j = 0; j < n; ++j) { F[i*n+j] = i + j; } } for ( i = 0; i < m; ++i) { printf("\n"); for ( j = 0; j < n; ++j) { printf("%lf ", F[i*n+j]); } } G = (double *) malloc (m*n*sizeof(double)); for ( i = 0; i < m; ++i) { for ( j = 0; j < n; ++j) { G[i*n+j] = i + j; } } printf("\n\n\n"); for ( i = 0; i < m; ++i) { printf("\n"); for ( j = 0; j < n; ++j) { printf("%lf ", G[i*n+j]); } } getchar(); A = (double *) malloc (m*n*sizeof(double)); for (i = 0; i < m*n; ++i) { for (j = 0, A[i] = 0; j < n; ++j) { A[i] = A[i] + F[n*i+j] * G[j*n+i]; } } printf("\n\n\n"); for ( i = 0; i < m; ++i) { printf("\n"); for ( j = 0; j < n; ++j) { printf("%lf ", A[i*n+j]); } } getchar(); return 0; }
Wo liegt der Fehler in meinen Überlegungen, dass nur die erste Zeile richtig bestimmt wird und in der zweiten Zeile schon der Anfangswert falsch ist. Bin ich etwa wieder mit dem Startwert 0 und 1 durcheinander gekommen oder ist der Zugriff auf die Elemente falsch programmiert? Bin ich unbedingt auf drei Schleifen angewiesen?
Mit F und G erzeuge ich mir dynamische Matrizen. Die Matrix A soll das Multiplikationsergebnis dieser beiden Matrizen sein.
-
Kannst du mal in einem kleinen Beispiel zeigen, wie du das haben willst? (Also 2 Matrizen mit Werten und dann die Summenmatrix mit Werten)
-
1 2 Matrix 1: 3 4 5 6 5*1 + 6*3 = 23 5*2 + 6*4 = 34 Matrix 2 Ergebnismatrix 3 7 8 7*1 + 8*3 = 31 7*2 + 8*4 = 46
Hier mal das Beispiel. Matrix 2 soll mit Matrix 1 multipliziert werden und Matrix 3 liefern. Da im Speicher die Werte der Reihen hintereinander stehen, bin ich mir mitlerweile sicher, dass es nur funktioniert, wennn man mit 3 Schleifen arbeitet. Ich knobble noch ein bisschen weiter rum. Eher gibt es heute kein Feierabend, bin aber für jede Fremdhilfe dankbar.
-
Stimmt es sind drei Schleifen, die du brauchst. Ich schätze mal du bist eh schon nah dran.
Wenn ich dein Beispiel richtig verstanden habe, dann willst du jede Zeile beider Matrizen durchgehen und dabei jede Spalte einer Zeile der ersten Matrix mit allen Spalten der gleichen Zeile der zweiten Matrix multiplizieren. Richtig?
-
Hallo AJ,
ich drücke es mal etwas anders aus, Du meinst bestimmt das gleiche. Ich will es mal in Formel beschreiben, was ich meine, wobei die Ziffern identisch der Speicherbelegung sind:
A0 A1 A2 A3 A4 A5 A6 A7 A8 B0 B1 B2 B3 B4 B5 Das sind die beiden Matrizen B6 B7 B8 Im Speicher stehen die Werte hintereinander = A0 ... A8 und B0 ... B8. Ich möchte Wert 0 der Matrix B mit Wert 0 der Matrix A multiplizieren dann dazuadieren Wert B1 multipliziert mit Wert A3 dann dazuadieren Wert B3 multipliziert mit Wert A6. Dass liefert den Weert C0. Und dann immer so weiter. Das ganze sieht dann so aus: C0 = A0*B0 + A3*B1 + A6*B2 C1 = A1*B0 + A4*B1 + A7*B2 C2 = A2*B0 + A5*B1 + A8*B2 C3 = A0*B3 + A3*B4 + A6*B5 C4 = A1*B3 + A4*B4 + A7*B5 C5 = A2*B3 + A5*B4 + A8*B5 C6 = A0*B6 + A3*B7 + A6*B8 C7 = A1*B6 + A4*B7 + A7*B8 C8 = A2*B6 + A5*B7 + A8*B8 Dahinter steckt ein Schema, nur gelingt es mir nicht so recht, dass mit den Schleifen abzubilden.In Worten ausgedrückt möchte ich die Summe bilden über jeden multiplizierten Wert einer Zeile der Matrix B mit dem entsprechend dazugehörigen Wert einer Spalte der Matrix A
Auch ich bin schon völlig verwirrt
-
Ich würde das ganze in einem zweidimensionalem Array lösen
A00 A01 A02 B00 B01 B02
A10 A11 A12 * B10 B11 B12
A20 A21 A22 B20 B21 B22Damit brauchst du drei Schleifen um C00 = A00 * B00 + A10 + B01 + A20 + B02 zu berechnen.
Wobei A m Zeilen hat und n Spalten
B hat n Zeilen und l Spaltenfor (int i = 0; i < m; i++) { for(int j = 0; j < n; j++) { C[j][i] = 0; for(int k = 0; k < l;k++) { C[j][i] += A[j][k]*B[k][i]; } } }
Probier es mal hiermit
-
Hallo Drops, AJ
danke für Eure Hilfe, habe es gelöst. Es geht auch mit 3 Schleifen, wenn alle Werte einer Matrix hintereinander gespeichert sind. Ich kann also auch auf ein zweidimensionales Array verzichten, was doch das Programm erheblich vereinfacht. Hier meine Testvariante, mit der die Matrixmultiplikation wunderbar funktioniert.
# include <stdio.h> # include <stdlib.h> # include <math.h> int main() { double *F, *G, *A; int i, j, k, m, n; printf("Eingabe der Zeilenanzahl: "); scanf("%d", &m); printf("Eingabe der Spaltenanzahl: "); scanf("%d", &n); F = (double *) malloc (m*n*sizeof(double)); for ( i = 0; i < m; ++i) { for ( j = 0; j < n; ++j) { F[i*n+j] = i*j; } } for ( i = 0; i < m; ++i) { printf("\n"); for ( j = 0; j < n; ++j) { printf("%lf ", F[i*n+j]); } } G = (double *) malloc (m*n*sizeof(double)); for ( i = 0; i < m; ++i) { for ( j = 0; j < n; ++j) { G[i*n+j] = i+j; } } printf("\n\n\n"); for ( i = 0; i < m; ++i) { printf("\n"); for ( j = 0; j < n; ++j) { printf("%lf ", G[i*n+j]); } } getchar(); A = (double *) malloc (m*n*sizeof(double)); for (i = 0; i < m; ++i) { for (j = 0; j < n; ++j) { for (k = 0, A[j+i*n] = 0; k < n; ++k) { A[j+i*n] = A[j+i*n] + F[k+i*n] * G[k*n+j]; } } } printf("\n\n\n"); for ( i = 0; i < m; ++i) { printf("\n"); for ( j = 0; j < n; ++j) { printf("%lf ", A[i*n+j]); } } getchar(); return 0; }
HURRA, FEIERABEND
.