Mit zweidimensionalem Array rechnen

#1
Moin,
ich bin im ersten Semester und fange gerade an C zu leren und ich komme bei folgendem Problem nicht weiter.

Code:
void MatrizenMultiplikation (float a[2][3], float b[3][2], float c[2][2])

{

    int a_max = 3, b_max = 2, c_max =2, i, j;

    for(i = 0; i < 2; i++)

    {

        for(j = 0; j < 2; j++)

        {

            c[j] = (a * b) + (a * b) + (a * b);

        }

    }

}
Unabhängig davon, dass ich noch nicht weiß wie ich das rechnerisch programmieren soll, komm ich schon nicht weiter, weil mir folgendes Error ausgegeben wird:
Code:
||=== Build file: "no target" in "no project" (compiler: unknown) ===|
F:\Testat 5\PA_5.c||In function 'MatrizenMultiplikation':|
F:\Testat 5\PA_5.c|10|error: invalid operands to binary * (have 'float (*)[3]' and 'float (*)[2]')|
F:\Testat 5\PA_5.c|10|error: invalid operands to binary * (have 'float (*)[3]' and 'float (*)[2]')|
F:\Testat 5\PA_5.c|10|error: invalid operands to binary * (have 'float (*)[3]' and 'float (*)[2]')|
||=== Build failed: 3 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
Ich hoffe ihr könnt mir helfen...danke im Vorraus und bis dann.
 
#3
Ups...danke.
C:
int main()
{
int i, j;
float a[2][3] = {{1, 2, 3},{4, 5, 6}};
float b[3][2] = {{-1, 0},{0, 1},{2, 1}};
float c[2][2];

MatrizenMultiplikation(a, b, c);

for(i = 0; i < 2; i++)
{
    for(j = 0; j < 2; j++)
    {
        printf("Die Multiplikation ergibt die neue Matrix c[%d][%d] = %f\n", i, j, c[i][j]);
    }
}

return 0;
}
 

German

Well-Known Member
c-b Experte
#4
Die 3 Fehler kommen daher, dass du Arrays multiplizieren willst. Das geht natürlich nicht. Nur die einzelnen Elemente (und damit meine ich runtergebrochen zum einzelnen float) lassen sich miteinander multiplizieren oder addieren.
Einschlägige Lösungen nutzen 3 ineinander verschachtelte for Schleifen zur Berechnung, bei denen zu den Elementen deines Arrays c hinzu addiert werden würde. Ergo - initialisiere c bei der Deklaration, sonst bekommst du mehr oder weniger zufällige Werte.
 

BAGZZlash

Well-Known Member
c-b Experte
#5
Unabhängig davon, dass ich noch nicht weiß wie ich das rechnerisch programmieren soll
Okay, dann lösen wir erstmal das unmittelbare Problem. Wie @German schon sagt liegt das Problem genau darin, dass Du eben elementweise rechnen musst. Hier mal eine Schablone, die das Problem löst, aber natürlich kein gutes Programm ist, denn der Kern der Aufgabe ist es ja, das manuelle Rechnen durch geschickte Schleifenimplementierung zu ersetzen. Das musst Du dann hier immer noch machen:

C:
#include <stdio.h>

void MatrizenMultiplikation (float a[2][3], float b[3][2], float c[2][2])

{
    c[0][0] = (a[0][0] * b[0][0]) + (a[0][1] * b[1][0]) + (a[0][2] * b[2][0]);
    c[0][1] = (a[0][0] * b[0][1]) + (a[0][1] * b[1][1]) + (a[0][2] * b[2][1]);
    c[1][0] = (a[1][0] * b[0][0]) + (a[1][1] * b[1][0]) + (a[1][2] * b[2][0]);
    c[1][1] = (a[1][0] * b[0][1]) + (a[1][1] * b[1][1]) + (a[1][2] * b[2][1]);
}

int main()
{
    int i, j;
    float a[2][3] = {{1, 2, 3}, {4, 5, 6}};
    float b[3][2] = {{-1, 0}, {0, 1}, {2, 1}};
    float c[2][2] = {{0, 0}, {0, 0}};
    
    MatrizenMultiplikation(a, b, c);
    
    for(i = 0; i < 2; i++)
    {
        for(j = 0; j < 2; j++)
        {
            printf("Die Multiplikation ergibt die neue Matrix c[%d][%d] = %f\n", i, j, c[i][j]);
        }
    }
}
 
#6
Vielen Dank, das hat schon geholfen. Eine frage hätte ich noch und zwar wie man das mit Zeigern lösen kann. Wie das mit Zeigern bei eindimensionalen Arrays funktioniert habe ich verstanden, aber für Mehrdimensionale Arrays weiß ich icht wie ich sie in eine Funktion übergeben kann. Ich hätte es so gemacht:

C:
#include <stdio.h>

void MatrizenMultiplikation (float *a, float *b, float *c)
{
    int a_max = 3, b_max = 2, c_max =2, i, j;
    for(i = 0; i < 2; i++)
    {
        for(j = 0; j < 2; j++)
        {
            c[i][j] = 0;//rechnung unfertig, für jeden Array 0 zuweisen
        }
    }


}


int main()
{
int i, j;
float a[2][3] = {{1, 2, 3},{4, 5, 6}};
float b[3][2] = {{-1, 0},{0, 1},{2, 1}};
float c[2][2];

MatrizenMultiplikation(a, b, c);

for(i = 0; i < 2; i++)
{
    for(j = 0; j < 2; j++)
    {
        printf("Die Multiplikation ergibt die neue Matrix c[%d][%d] = %f\n", i, j, c[i][j]);
    }
}

return 0;
}
Dann erhalte ich folgende warnings:


C:
||=== Build file: "no target" in "no project" (compiler: unknown) ===|
F:\Testat 5\PA_5.c||In function 'MatrizenMultiplikation':|
F:\Testat 5\PA_5.c|10|error: subscripted value is neither array nor pointer nor vector|
F:\Testat 5\PA_5.c||In function 'main':|
F:\Testat 5\PA_5.c|25|warning: passing argument 1 of 'MatrizenMultiplikation' from incompatible pointer type [-Wincompatible-pointer-types]|
F:\Testat 5\PA_5.c|3|note: expected 'float *' but argument is of type 'float (*)[3]'|
F:\Testat 5\PA_5.c|25|warning: passing argument 2 of 'MatrizenMultiplikation' from incompatible pointer type [-Wincompatible-pointer-types]|
F:\Testat 5\PA_5.c|3|note: expected 'float *' but argument is of type 'float (*)[2]'|
F:\Testat 5\PA_5.c|25|warning: passing argument 3 of 'MatrizenMultiplikation' from incompatible pointer type [-Wincompatible-pointer-types]|
F:\Testat 5\PA_5.c|3|note: expected 'float *' but argument is of type 'float (*)[2]'|
||=== Build failed: 1 error(s), 3 warning(s) (0 minute(s), 0 second(s)) ===|
 
#8
void MatrizenMultiplikation (float a[][3], float b[][2], float c[][2])
… beispielsweise.
Okay, aber warum kann ich dann nicht wie gewohnt mit den Zeigern rechnen? Wie z.B. hier:
C:
void MatrizenMultiplikation (float a[][3], float b[][2], float c[][2])
{
    int a_max = 3, b_max = 2, c_max =2;
    c[0][0] = (*a * *b) + (*(a + 1) * *(b + b_max)) + (*(a + 2) * *(b + (2 * b_max)));
    c[0][1] = 0;//(a[0][0] * b[0][1]) + (a[0][1] * b[1][1]) + (a[0][2] * b[2][1]);
    c[1][0] = 0;//(a[1][0] * b[0][0]) + (a[1][1] * b[1][0]) + (a[1][2] * b[2][0]);
    c[1][1] = 0;//(a[1][0] * b[0][1]) + (a[1][1] * b[1][1]) + (a[1][2] * b[2][1]);
}
folgende Fehlermeldung:
C:
||=== Build file: "no target" in "no project" (compiler: unknown) ===|
F:\Testat 5\PA_5unfertig.c||In function 'MatrizenMultiplikation':|
F:\Testat 5\PA_5unfertig.c|4|error: invalid operands to binary * (have 'float *' and 'float *')|
F:\Testat 5\PA_5unfertig.c|4|error: invalid operands to binary * (have 'float *' and 'float *')|
F:\Testat 5\PA_5unfertig.c|4|error: invalid operands to binary * (have 'float *' and 'float *')|
||=== Build failed: 3 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|
 

BAGZZlash

Well-Known Member
c-b Experte
#9
Trotz Zeigern wirst Du elementweise arbeiten müssen. Aber bitte löse doch die Aufgabe erst mal ohne Zeiger. Dann wird sich vieles aufklären, denke ich.
 

German

Well-Known Member
c-b Experte
#10
aber warum kann ich dann nicht wie gewohnt mit den Zeigern rechnen?
Weil du eben so gar nicht wie gewohnt mit Zeigern rechnest. Seit wann lassen sich Zeiger multiplizieren? Wie gesagt, du kannst/sollst/musst mit den einzelnen float Elementen rechnen.
Hint: "matrix multiplication in c" wären englische Suchbegriffe. Mann muss nicht alles wissen oder das Rad neu erfinden, wenn man weiß wo man es findet.
 
#11
Die 3 Fehler kommen daher, dass du Arrays multiplizieren willst. Das geht natürlich nicht. Nur die einzelnen Elemente (und damit meine ich runtergebrochen zum einzelnen float) lassen sich miteinander multiplizieren oder addieren.
Einschlägige Lösungen nutzen 3 ineinander verschachtelte for Schleifen zur Berechnung, bei denen zu den Elementen deines Arrays c hinzu addiert werden würde. Ergo - initialisiere c bei der Deklaration, sonst bekommst du mehr oder weniger zufällige Werte.
Ich musste es mir zwar mehrmals durchlesen, aber es hat sehr geholfen.
Hab noch nie vorher ein Forum genutzt aber bin begeistert! Danke euch beiden, ihr habt mir geholfen, habe die Lösung...schönes Gefühl.
C:
#include <stdio.h>

void MatrizenMultiplikation (float a[][3], float b[][2], float c[][2])
{
    int i, j, k;
    for(i = 0; i < 2; i++)
    {
        for(j = 0; j < 2; j++)
        {
            for(k = 0; k < 3; k++)
                c[i][j] += (a[i][k] * b[k][j]); //(a[(k-k+i)][(k)] * b[(k)][(k-k+j)]), k - k immer 0
        }
    }
}

int main()
{
    int i, j;
    float a[2][3] = {{1, 2, 3}, {4, 5, 6}};
    float b[3][2] = {{-1, 0}, {0, 1}, {2, 1}};
    float c[2][2] = {{0, 0}, {0, 0}};

    MatrizenMultiplikation(a, b, c);

    for(i = 0; i < 2; i++)
    {
        for(j = 0; j < 2; j++)
        {
            printf("Die Multiplikation ergibt die neue Matrix c[%d][%d] = %f\n", i, j, c[i][j]);
        }
    }
}
 

German

Well-Known Member
c-b Experte
#12
float c[2][2] = {0}; Wäre die einfachere Schreibweise für die Initialisierung aller Elemente mit 0.
Mir hat in dem Zusammenhang übrigens dein c[i][j] = 0; ganz gut gefallen. Einfach über for(k... wieder einfügen, dann funktioniert die Funktion auch mit dem uninitialisierten Array einwandfrei. (Was nicht bedeuten soll, dass du Variablen nicht grundsätzlich initialisieren solltest. Ganz im Gegenteil.)
 
#13
float c[2][2] = {0}; Wäre die einfachere Schreibweise für die Initialisierung aller Elemente mit 0.
Mir hat in dem Zusammenhang übrigens dein c[i][j] = 0; ganz gut gefallen. Einfach über for(k... wieder einfügen, dann funktioniert die Funktion auch mit dem uninitialisierten Array einwandfrei. (Was nicht bedeuten soll, dass du Variablen nicht grundsätzlich initialisieren solltest. Ganz im Gegenteil.)
Ja, da hast du recht danke.
 
Oben