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 B22

    Damit 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 Spalten

    for (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 😃 .


Anmelden zum Antworten