2016-10-14 13 views
1

Ich habe ein Programm erstellt, das Matrix Addition, Subtraktion und Multiplikation tut. Ich habe die Additions- und Subtraktionsabschnitte behandelt, aber als ich die Multiplikation erreichte, habe ich Probleme, die korrekten Werte auszugeben. Ich habe den Code nur mit der Multiplikationsfunktion unten platziert.Matrix Multiplikation - C

#define _CRT_SECURE_NO_WARNINGS 

#include <stdio.h> 
#include <stdlib.h> 

typedef struct { 

int *elements; 
int rows; 
int columns; 

} matrix; 

void main() { 

     matrix a, b, c; 

     void read_matrix(matrix *); 
     void deallocate(matrix *); 
     void print(matrix); 
     matrix add(matrix, matrix); 
     matrix subtract(matrix, matrix); 
     matrix multiply(matrix, matrix); 

     read_matrix(&a); 
     read_matrix(&b); 
     /* 
     c = add(a, b); 
     printf("The answer of Matrix (a + b) is \n\n"); 
     print(a); 
     printf("\n +\n\n"); 
     print(b); 
     printf("\n =\n\n"); 
     print(c); 
     printf("\n"); 

     deallocate(&c); 
     c = subtract(a, b); 
     printf("The answer of Matrix (a - b) is \n\n"); 
     print(a); 
     printf("\n -\n\n"); 
     print(b); 
     printf("\n =\n\n"); 
     print(c); 
     printf("\n"); 

     deallocate(&c); 
     */ 
     c = multiply(a, b); 
     printf("The answer of Matrix (a * b) is \n\n"); 
     print(a); 
     printf("\n *\n\n"); 
     print(b); 
     printf("\n =\n\n"); 
     print(c); 
     printf("\n"); 

} 

void read_matrix(matrix *z) { 

     int d1, d2, allc, i, x, y, j, val; 
     int res; 

     printf("\nWhat is the first dimension of the array? "); 
     res = scanf("%d", &d1); 

     if (res != 1) { 
      fprintf(stderr, "Something went wrong with your first dimension!"); 
        return; 
     } 

     printf("What is the second dimension of the array? "); 
     res = scanf("%d", &d2); 
     if (res != 1) { 
      fprintf(stderr, "Something went wrong with your second dimension!"); 
      return; 
     } 

     printf("Matrix Dimension is %dx%d\n", d1, d2); 

     allc = d1*d2; 

     (*z).elements = (int *)calloc(allc, sizeof(int)); 
     (*z).rows = d1; 
     (*z).columns = d2; 

     x = 0; 
     j = 0; 

     printf("\n"); 

     for (i = 0; i < d1; i++) { 

      x++; 

      for (y = 0; y < d2; y++) { 
       printf("Enter the value for row %d column %d: ", x, y + 1); 
       res = scanf("%d", &val); 
       if (res != 1) { 
        fprintf(stderr, "Something went wrong while reading value %d\n", x); 
        return; 
       } 

       (*z).elements[j++] = val; 
      } 

     } 
    } 

    void deallocate(matrix *c) { 

     free((*c).elements); 
     (*c).elements = NULL; 
     (*c).rows = 0; 
     (*c).columns = 0; 
    } 

    void print(matrix z) { 

     int i, j, x; 
     x = 0; 

     for (i = 0; i < z.rows; i++) { 

      printf("[ "); 

      for (j = 0; j < z.columns; j++) { 

       printf("%-4d", z.elements[x++]); 
      } 
      printf("]\n"); 
     } 
    } 

    matrix multiply(matrix a, matrix b) { 

     matrix c; 

     int a1, a2, b1, b2, allc, i, j, x, y, z, alc, addval, val; 

     i = 0; 
     j = 0; 
     alc = 0; 
     val = 0; 
     addval = 0; 

     a1 = a.rows; 
     a2 = a.columns; 
     b1 = b.rows; 
     b2 = b.columns; 

     allc = (a1 * b2); 

     c.elements = (int *)calloc(allc, sizeof(int)); 
     c.columns = a1; 
     c.rows = b2; 

     if (a2 != b1) { 
      printf("\n\nThe inner dimensions of your matrices do not match! Multiplication cannot be done!\n\n"); 
      exit(1); 
     } 


     for (x = 0; x < c.rows; x++) { 

      for (y = 0; y < c.rows; y++) { 

       for (z = 0; z < c.rows; z++) { 

        i = (i * c.rows); 

        addval = (a.elements[j]) * (b.elements[i]); 

        val += addval; 

        j++; 
        i++; 
       } 
       c.elements[alc] = val; 
       printf("VAL IS: %d\n\n", val); 

       val = 0; 

       i = 0; 
       alc++; 
      } 
     } 

     printf("\n\n"); 

     return c; 
    } 

In der Multiplikationsfunktion wird die dreifache verschachtelte for-Schleife soll durch oft genug gehen, die richtige Anzahl der Elemente für die Dimension des neuen Arrays zu drucken. Ich weiß, wie man Matrixmultiplikation macht, aber ich bin mir nicht sicher, ob ich es hier korrekt dargestellt habe.

Der Ausgang für ein Beispiel ist:

What is the first dimension of the array? 3 
What is the second dimension of the array? 3 
Matrix Dimension is 3x3 

Enter the value for row 1 column 1: 1 
Enter the value for row 1 column 2: 2 
Enter the value for row 1 column 3: 3 
Enter the value for row 2 column 1: 4 
Enter the value for row 2 column 2: 5 
Enter the value for row 2 column 3: 6 
Enter the value for row 3 column 1: 7 
Enter the value for row 3 column 2: 8 
Enter the value for row 3 column 3: 9 

What is the first dimension of the array? 3 
What is the second dimension of the array? 3 
Matrix Dimension is 3x3 

Enter the value for row 1 column 1: 1 
Enter the value for row 1 column 2: 2 
Enter the value for row 1 column 3: 3 
Enter the value for row 2 column 1: 4 
Enter the value for row 2 column 2: 5 
Enter the value for row 2 column 3: 6 
Enter the value for row 3 column 1: 7 
Enter the value for row 3 column 2: 8 
Enter the value for row 3 column 3: 9 


The answer of Matrix (a * b) is 

[ 1 2 3 ] 
[ 4 5 6 ] 
[ 7 8 9 ] 

    * 

[ 1 2 3 ] 
[ 4 5 6 ] 
[ 7 8 9 ] 

    = 

[ 216847534336951265054271] 
[ 1641572693-138635672036124672] 
[ 1352368309-50514195286739134] 

Press any key to continue . . . 
+0

x, y und z zählen alle Zeilen. Ich erwarte, dass mindestens einer von ihnen Spalten zählen sollte. Und "i" wird mit "c.rows" multipliziert und dann bei jedem Durchgang durch die Schleife inkrementiert. Verwenden Sie ein "printf", um den Wert von "i" zu drucken, und Sie werden sehen, dass es nicht das ist, was Sie wollen. – user3386109

+0

Off topic: in der 'print' Funktion würde ich"% -4d "' in '"% -3d "' ändern. Das hält die Zahlen davon ab, alle zusammen zu bündeln, wenn einige länger als drei Ziffern sind. – user3386109

Antwort

0

Im Folgenden meine Nacharbeiten des Codes ist die Matrixmultiplikation der Fall ist. Das Problem war mit Ihrer multiply() Funktion. Sie können sehen, dass es mit der a Matrix verloren geht, indem Sie nur die Variable j inkrementieren - in einer Arbeitslösung nimmt jedes Element der Matrix a mehrfach an der Multiplikation teil.

Ich änderte auch Ihre Routinen zu allen Pass-Zeigern zu Matrix-Strukturen, anstatt Ihre Mischung aus übergebenen Zeigern und Weitergabe/Rückgabe Matrixstrukturen direkt nach Wert. Ich denke, das ist konsistenter und einfacher zu folgen, aber es bedeutet, dass Sie Ihre anderen Matrix-Mathe-Routinen ändern müssen, um genauso zu arbeiten, wenn Sie es so halten.

#include <stdio.h> 
#include <stdlib.h> 

typedef struct { 
    int *elements; 
    int rows; 
    int columns; 
} matrix; 

void read_matrix(matrix *z) { 

    int d1, d2, val; 

    printf("\nWhat is the first dimension of the array? "); 
    int result = scanf("%d", &d1); 

    if (result != 1) { 
     fprintf(stderr, "Something went wrong with your first dimension!\n"); 
     exit(1); 
    } 

    printf("What is the second dimension of the array? "); 
    result = scanf("%d", &d2); 
    if (result != 1) { 
     fprintf(stderr, "Something went wrong with your second dimension!\n"); 
     exit(1); 
    } 

    printf("Matrix Dimension is %dx%d\n", d1, d2); 

    z->elements = calloc(d1 * d2, sizeof(int)); 
    z->rows = d1; 
    z->columns = d2; 

    int x = 0; 
    int j = 0; 

    printf("\n"); 

    for (int i = 0; i < d1; i++) { 

     x++; 

     for (int y = 0; y < d2; y++) { 
      printf("Enter the value for row %d column %d: ", x, y + 1); 
      result = scanf("%d", &val); 
      if (result != 1) { 
       fprintf(stderr, "Something went wrong while reading value (%d, %d)\n", x, y + 1); 
       exit(1); 
      } 

      z->elements[j++] = val; 
     } 
    } 
} 

void deallocate(matrix *c) { 

    free(c->elements); 

    c->elements = NULL; 
    c->rows = 0; 
    c->columns = 0; 
} 

void print(matrix *z) { 

    int x = 0; 

    for (int i = 0; i < z->rows; i++) { 

     printf("[ "); 

     for (int j = 0; j < z->columns; j++) { 

      printf("%-4d", z->elements[x++]); 
     } 

     printf("]\n"); 
    } 
} 

void multiply(matrix *a, matrix *b, matrix *c) { 

    if (a->columns != b->rows) { 
     fprintf(stderr, "The inner dimensions of your matrices do not match! Multiplication cannot be done!\n"); 
     exit(1); 
    } 

    c->elements = calloc(a->rows * b->columns, sizeof(int)); 
    c->columns = b->columns; 
    c->rows = a->rows; 

    int alc = 0; 

    for (int x = 0; x < a->rows; x++) { 

     for (int y = 0; y < b->columns; y++) { 

      int value = 0; 

      for (int z = 0; z < b->rows; z++) { 

       value += a->elements[z + x * a->columns] * b->elements[y + z * b->columns]; 
      } 

      c->elements[alc++] = value; 
     } 
    } 
} 

int main() { 

    matrix a, b, c; 

    read_matrix(&a); 
    read_matrix(&b); 

    multiply(&a, &b, &c); 

    printf("The answer of Matrix (a * b) is \n\n"); 
    print(&a); 
    printf("\n *\n\n"); 
    print(&b); 
    printf("\n =\n\n"); 
    print(&c); 
    printf("\n"); 

    deallocate(&a); 
    deallocate(&b); 
    deallocate(&c); 

    return 0; 
} 
+0

Eine weitere sinnvolle Lösung für halbtransparente Strukturen (wie z. B. nur für Funktionsaufrufe) ist das 'typedef 'der Struktur als Name, der ein Array der Größe 1 ist. GMP tut dies mit 'mpz_t', also können Sie sie mit (fast) nahtloser impliziter Pass-by-Pointer-Semantik weiterleiten, ohne die Notwendigkeit, Zeiger explizit zu akzeptieren und Zeiger zu übergeben, während die Stapelzuordnung der Basisstruktur einfach bleibt. – ShadowRanger

+0

Vielen Dank für die Antwort! Alle Funktionen und ihre Partner waren wie von meinem Professor für das Labor gefordert. Wenn ich mich verändert hätte, hätte ich es auch getan. Danke für die Antwort! –

+0

@ T.Gon Es gibt verschiedene Mechanismen, um die Dankbarkeit für einen Beitrag zu zeigen. Wenn du denkst, dass ein Beitrag (Fragen brauchen Stimmen, auch) nützlich (hilfreich? Illuminative?), * Upvote es * (10 rep). Wenn eine Antwort Ihr Problem löst (oder am hilfreichsten war, um eine Lösung zu erreichen), akzeptieren Sie * it (15 rep). Wenn Sie der Meinung sind, dass die beste Antwort auf eine Frage einen zusätzlichen Kredit verdient, starten Sie eine Bounty (Übertragung der Reputation von Ihrem Konto und möglicherweise von jemand anderem). – greybeard