Hilfe bei Matrixmultiplikation in C als Funktion



  • HansKlaus schrieb:

    also auf die einzelnen Elemente einer Matrix greifst du z.B. so zu:

    *(matrix+zeile*anzahl_spalten+spalte)=wert;
    

    das 1. Element in der 1. Spalte ist also *(matrix+0), das zweite *(matrix+1).
    das 1. Element in der 2. spalte *(matrix+1*anzahlspalten+0), also bei einer Matrix mit 10 Spalten *(matrix+10) usw.

    vereinfacht gesagt zeigt *matrix auf das 1. Element und *(matrix+x) auf das x-te Element, den Rest machen dann die Kenntnisse der Mathematik.

    Dann soltest du auch dazu schreiben, wie matrix definiert ist.
    Nur so viel: *int (matrix)[10] ist es nicht.

    ^(Im Übrigen hatte ich das auch schon geschrieben.)^



  • naja er wollte doch Zeigerarithmetik benutzen, also kann man doch schreiben

    int funktion(int *matrix)
    {
    *(matrix+3*10+3)=0; //zulässig
    matrix[3][4]=0; //auch zulässig aber keine Zeigerarithmetik
    }
    
    int main()
    {
    int matrix[10][10];
    
    funktion(matrix);
    }
    

    oder sehe ich das falsch?



  • Wofür ist denn Summe als Paramter von multiplikation?.
    Wenn der Wert ungleich 0 ist, kommt Müll raus.

    Summe dient als Zwischenspeicherung der Zwischenergebnisse der einzelnen Rechnung. Diese werden so lange aufsummiert, dass der Wert des Ergebnisvektors herauskommt.
    Außerdem wird summe nach jeder Übergabe an den Ergebnisvektor wieder auf 0 zurückgesetzt.

    Ich verstehe jetzt nicht, in wie fern man mit Pointern rechnen kann.
    Eigentlich enthalten die ja nur die Adresse. Gibt es da nicht dieses "Gegensymbol &", um den Inhalt der (nicht-Pointer) Variable wieder hervorzuholen?



  • ja genau Pointer zeigen auf eine Adresse.

    wenn du z.B. schreibst

    int *pointer;
    
    pointer=0;
    

    zeigt dieser auf die Adresse 0 (wir nehmen jetzt mal für die Zukunft an, dass dir das Betriebssystem keine Speicherzugriffsverletzung um die Ohren haut) und du kannst über

    *pointer=12345;
    

    den Wert 12345 an die Adresse 0 schreiben. Schreibst du dann

    *(pointer + 1)=23456;
    

    so wird in die um 1 erhöhte Adresse in pointer (also 1) der Wert 23456 geschrieben. Also vereinfacht gesagt: mit * schreibst du irgendwas in die Adresse rein, ohne *legst du die Adresse fest.

    Das & gibt die Adresse der Variable raus, also wenn du möchtest, dass pointer auf x zeigt, schreibst du pointer=&x, und wenn du möchtest, dass pointer auf die zweite Zeile von matrix zeigt, schreibst du pointer = matrix[1]; 😃



  • HansKlaus schrieb:

    naja er wollte doch Zeigerarithmetik benutzen, also kann man doch schreiben

    int funktion(int *matrix)
    {
    *(matrix+3*10+3)=0; //zulässig
    matrix[3][4]=0; //auch zulässig aber keine Zeigerarithmetik
    }
    
    int main()
    {
    int matrix[10][10];
    
    funktion(matrix);
    }
    

    oder sehe ich das falsch?

    Ja, siehst du.

    In funktion kannst du matrix nicht zweimal dreferenzieren. Das versuchst du mit matrix[3][4]
    funktion erwartet einen Zeiger auf int.
    matrix (nur der Name) ist in main aber die Adresse von 10 Arrays aus Arrays von 10 int

    Auch wenn die Adresse identisch ist, warnt da der Compiler.



  • Broetchen93 schrieb:

    Wofür ist denn Summe als Paramter von multiplikation?.
    Wenn der Wert ungleich 0 ist, kommt Müll raus.

    Summe dient als Zwischenspeicherung der Zwischenergebnisse der einzelnen Rechnung. Diese werden so lange aufsummiert, dass der Wert des Ergebnisvektors herauskommt.
    Außerdem wird summe nach jeder Übergabe an den Ergebnisvektor wieder auf 0 zurückgesetzt.

    Ich wollte nicht wissen wozu Summe da ist, sondern warum es als Paramter von multiplikation auftritt.
    Warum übergibst du Summe von außen in die Funktion?

    Broetchen93 schrieb:

    Ich verstehe jetzt nicht, in wie fern man mit Pointern rechnen kann.
    Eigentlich enthalten die ja nur die Adresse. Gibt es da nicht dieses "Gegensymbol &", um den Inhalt der (nicht-Pointer) Variable wieder hervorzuholen?

    Zeiger sind auch nur Variablen. Sie Speichern keinen Zahlenwert (oder Zeichen) sondern Adressen.
    Damit kann man auch rechnen.
    Du kannst die Differenz ausrechnen oder einen Offset dazu rechnen.
    Du kannst auch die Adresse (den Inhalt) verändern.

    & ist der Adressoperator. Du ermittelst die Referenz.
    Mit * (oder []) dereferenzierst du.

    Der Compiler macht beim übersetzen aus array[4] gleich *(array+4)



  • Okay.. die Syntax stimmt jetzt immerhin, jetzt kommt noch der logische Teil der Rechnung.

    Summe = Summe + *(matrix1+h1*a2+h3)**(matrix2+h3*b2+h2);
    

    So sieht meine Rechenzeile gerade aus.
    Am Anfang bin ich in Zeile 0 von Matrix1, die Matrix hat ein Maximum von a2 Spalten und befindet sich zu Anfang in der Spalte h3=0. Also sollte hier eigentlich die allererste Eingabe eingelesen werden, bzw. verrechnet werden.
    Das Ergebnis

    *(ergebnis + h1 * b2 + h2) = Summe;
    

    Sieht allerdings alles anders als zufriedenstellend aus.

    Warum übergibst du Summe von außen in die Funktion?

    War noch aus der alten Version. Ich habs jetzt abgeändert.



  • DirkB schrieb:

    Auch wenn die Adresse identisch ist, warnt da der Compiler.

    Das stimmt natürlich. Aber bei C kann ich ja (wieder von geschützten oder sonstwie dem Betriebssystem nicht angemeldeten Bereichen abgesehen) "einfach mal so" was in den Speicher schreiben.

    aber mir ist gerade aufgefallen, dass matrix[3][4] gar nicht funktioniert. woher soll der Compiler auch wiessen, wie er das zuordnen soll?

    Sieht allerdings alles anders als zufriedenstellend aus.

    sicher, dass du da nichts vertauscht hast? wenn doch: jetzt weißt du, warum man dir erzählt hat, dass klar verständliche Variablennamen verwendet werden sollen. 😃



  • sicher, dass du da nichts vertauscht hast? wenn doch: jetzt weißt du, warum man dir erzählt hat, dass klar verständliche Variablennamen verwendet werden sollen. :D
    

    Ganz im Gegenteil, aber nur was und wo?. Ich checke nochmal nach der Vorlage alles durch

    *(zeigeraufint + z * SPALTEN + s)
    

    SPALTEN bedeutet doch die maximale Anzahl der Spalten, oder?



  • HansKlaus schrieb:

    Aber bei C kann ich ja (wieder von geschützten oder sonstwie dem Betriebssystem nicht angemeldeten Bereichen abgesehen) "einfach mal so" was in den Speicher schreiben.

    Trottel. Wenn du keine Ahnung hast, halt einfach die Klappe. Du verleitest nur die Leser hier, deinen Unsinn zu glauben.

    HansKlaus schrieb:

    aber mir ist gerade aufgefallen, dass matrix[3][4] gar nicht funktioniert. woher soll der Compiler auch wiessen, wie er das zuordnen soll?

    Genau. Der Compiler weiß, im Gegensatz zu dir, was er tut. Und deshalb war dieser Hinweis von dir blanker Unsinn.



  • naja es bedeutet die anzahl der spalten, die die matrix hat, nicht die anzahl der spalten, die sie maximal haben kann.



  • Deine Arrayzeilen haben 10 Elemente. Davon hast du möglicherweise nur einen Teil beschrieben.
    Daher ist deine Berechnung nicht richtig.

    Du kannst es dir ja selber aufmalen.

    0 1 2 3 4 5 6 7 8 9
       +-+-+-+-+-+-+-+-+-+-+
     0 |x|x|x|x|x| | | | | | 
       +-+-+-+-+-+-+-+-+-+-+
     1 |x|x|x|x|x| | | | | | 
       +-+-+-+-+-+-+-+-+-+-+
     2 |x|x|x|x|a| | | | | | 
       +-+-+-+-+-+-+-+-+-+-+
     3 | | | | | | | | | | | 
       +-+-+-+-+-+-+-+-+-+-+
     4 | | | | | | | | | | | 
       +-+-+-+-+-+-+-+-+-+-+
     5 | | | | | | | | | | | 
       +-+-+-+-+-+-+-+-+-+-+
     6 | | | | | | | | | | | 
       +-+-+-+-+-+-+-+-+-+-+
     7 | | | | | | | | | | | 
       +-+-+-+-+-+-+-+-+-+-+
     8 | | | | | | | | | | | 
       +-+-+-+-+-+-+-+-+-+-+
     9 | | | | | | | | | | | 
       +-+-+-+-+-+-+-+-+-+-+
    

    Der Offset vom a vom Anfang des Array ist 2 * 10 + 4 = 24.
    Auch wenn der gefüllte Bereich nur 3 * 5 Elemente hat.



  • Wutz schrieb:

    Trottel. Wenn du keine Ahnung hast, halt einfach die Klappe. Du verleitest nur die Leser hier, deinen Unsinn zu glauben.

    wieso ich hab doch ahnung......
    C überlässt es dem Programmierer, wo er seine Daten hinschreibt. Deshalb gibt es z.B. auch keinen Schutz vor irgendwelchen Pufferüberläufen o.Ä..

    Der Compiler weiß, im Gegensatz zu dir, was er tut.

    deshalb gibt er ja auch nur eine Warnung aus und keinen Fehler 😉



  • HansKlaus schrieb:

    Wutz schrieb:

    Trottel. Wenn du keine Ahnung hast, halt einfach die Klappe. Du verleitest nur die Leser hier, deinen Unsinn zu glauben.

    wieso ich hab doch ahnung......
    C überlässt es dem Programmierer, wo er seine Daten hinschreibt. Deshalb gibt es z.B. auch keinen Schutz vor irgendwelchen Pufferüberläufen o.Ä..

    Es ist trotzdem nicht erlaubt und gibt, wenn du es trotzdem machst, undefined behaviour .
    D.h. es kann alles passieren; vom Formatieren deiner Festplatte, Tod der nächsten Katze oder der III. Weltkrieg.

    Der mangelnde Schutz ist der Einfachheit der Sprache geschuldet und der Tatsache, dass sie ein Werkzeug für Profis ist.



  • HansKlaus schrieb:

    C überlässt es dem Programmierer, wo er seine Daten hinschreibt. Deshalb gibt es z.B. auch keinen Schutz vor irgendwelchen Pufferüberläufen o.Ä..

    Falls es noch nicht deutlich genug war: Nein, du hast keinerlei Ahnung von C.
    Deine Annahmen darüber, warum wohl in C irgendwas so sei wie du es dir vorstellst sind einfach nur naiver Blödsinn, so wie alle deine bisherigen Beiträge.
    Du hast keine Ahnung von C, verschone die Welt mit deinem stümperhaften Halbwissen.



  • Okay Moment, meine Arrays haben alle 10 Zeilen und Spalten, somit können maximal 10*10 Matrizen verrechnet werden.
    Ich beziehe mich jetzt auf matrix1 aus der Zeile

    Summe = Summe + *(matrix1+h1*a2+h3)**(matrix2+h3*b2+h2);
    

    Deine Blaupause war ja:

    *(zeigeraufint + z * SPALTEN + s)
    

    Ich starte für die Zeilen bei h1, also bei 0 laut äußerer for-schleife.
    Dann habe ich in matrix1 für a2 die in main eingegebene Spaltenanzahl und für h3 die 0te Spalte.
    D.h. Ich befinde mich für die erste Matrix hier:(a2 für die Spaltenanzahl als Beispiel=3 gewählt)

    +-+-+-+-+-a2
     0 |x| | | 
       +-+-+-+
     1 | | | | 
       +-+-+-+
     2 | | | |  
       +-+-+-+
    

    Wenn ich jetzt z.B. die Zahlen von 1-9 eintragen lasse, befinde ich mich also bei 1.
    Bei der 2. Matrix habe ich h3 als Zeile definiert, ebenfalls noch 0.
    Außerdem ist die größe b2 und die aktuelle Spaltenkoordinate h2.

    +-+-+-+-+-b2
     0 |x| | | 
       +-+-+-+
     1 | | | | 
       +-+-+-+
     2 | | | |  
       +-+-+-+
    

    Wenn ich wieder die Zahlen von 1-9 eintrage, bin ich jetzt auch bei der 1.
    Habe ich also Summe= 0+1*1=1
    nächste Runde: h3 wird hochgezählt=1

    +-+-+-+-+-a2
     0 | |x| | 
       +-+-+-+
     1 | | | | 
       +-+-+-+
     2 | | | |  
       +-+-+-+
    

    Sind wir also bei der 2

    +-+-+-+-+-b2
     0 | | | | 
       +-+-+-+
     1 |x| | | 
       +-+-+-+
     2 | | | |  
       +-+-+-+
    

    Hier sind wir bei der 4, also Summe=1+24=9
    Und danach bei Summe=9+3
    7, also 30, was das Endergebnis für die erste Koordinate des Ergebnisses ist.
    Das wird jetzt in der 2. Schleife zugewiesen, und zwar ergebnis h1,h2, jeweils die 0te Koordniate.
    Danach wird Summe zurückgesetzt und h2 einen hochgezählt und alles beginnt von vorne für die nächste Spalte zunächst.



  • sicherlich. diese ganzen schutzmechanismen in anderen programmiersprachen nehmen einem irgendwie die sorgfaltspflicht ab, andererseits kann man gerade mit c/c++ wunderbar auf die hardware zugreifen und unglaublich effiziente programme schreiben.

    ich wollte mich jetzt auch nicht großartig streiten.

    wenn es heißt, das zeigerarithmetik verwendet werden soll (was sicherlich nicht ohne grund geschieht!), erkläre ich es eben auch in zeigerarithmetik.
    wenn ich *(zeiger+offset) schreibe, gehe ich auch davon aus, dass der speicher entsprechend angelegt wurde.

    außerdem hat man mir erklärt, dass all das, was man so im 1. semester erklärt bekommt (keine globalen variablen, kein goto, kein code den man nicht sofort versteht, keine compilerwarnungen usw. ) sehr schnell hinfällig ist, weil das ganze einfach rechenzeit kostet oder den Programmierer ersetzbar macht. 😃



  • also du musst immer *(matrix1+spalte+zeile*anzahlspalten) * (matrix+spalteanzahlspalten+zeile) zusammen zählen.

    unter der voraussetzung, dass die zweite matrix transponiert ist natürlich.



  • wobei sich anzahlspalten natürlich auf die tatsächliche anzahl bezieht.
    wenn du also eine 10*10 matrix hast, ist anzahlspalten auch 10, erstellst du ein array mit 10*10 elementen, schreibst da aber nur eine 3*5 matrix rein, so ist anzahlspalten auch 10, obwohl du nur 3 spalten hast.



  • Das Transponieren habe ich ja so bewerkstelligt, dass in der 1. matrix spaltenweise schnell gezählt wird und in der 2. matrix zeilenweise.


Anmelden zum Antworten