Sorry, so im Detail habe ich mich noch nie damit beschäftigt. Müsste selber irgendwo nachlesen und ein paar Dinge ausprobieren, und darauf habe ich im Moment keine Lust.
Beiträge von Jakube
-
-
Vielleicht kannst du das eine Zeichen wieder zurückschreiben oder zumindest zwischenspeichern.
Ein einfacher Ausweg wäre aber, dass man nach jeder Eingabe einen Beistrich setzen muss, im Sinn von 1/2, 4, 4/3, 3, ...
-
Wir wär's mit einem else bei deiner if(tmp==`/`) Abfrage. Wenn es keinen Nenner gibt, dann initialisierst du deinen Bruch einfach mit (zähler,1).
-
Ich finde die Idee eine ganze Zeile mittels dem >>-Operator einzulesen generell nicht gut (Ich würde so etwas zumindest selber nicht machen).
Durch Logging habe ich gesehen, dass ohnehin immer wieder die Zeile gelöscht wird. Außerdem wird die >>-Operation schon aufgerufen, ohne dass man irgendwelche Eingaben macht und im ersten Bruch steht dann ein ganz sonderbarer Wert.Ich würde einfach eine Zeile mit cin einlesen. Und dann diese ganz normal verarbeiten. Mein Beispielscode ist sicher nicht der beste, aber weiter möchte ich mich damit auch nicht befassen.
C
Alles anzeigen#include <iostream>#include <math.h> #include <sstream> using namespace std; class Bruch { public: int zaehler, nenner; Bruch() : zaehler(0), nenner(1) {} Bruch(string str) //erzeugt aus den ersten Zeichen einen Bruch { char tmp; stringstream ss; ss.str(str); ss >> zaehler; ss >> tmp; if(tmp == '/') ss >> nenner; else nenner = 1; } }; ostream& operator<<(ostream &s, Bruch b) { s << b.zaehler << "/" << b.nenner; return s; } int main() { const int max = 2; Bruch** Matrix = new Bruch*[max]; for (int i = 0; i < max ; i++) Matrix[i] = new Bruch[max]; Bruch *Ergebnis = new Bruch[max]; cout << "Bitte geben Sie alle Koeffizienten durch einen Beistrich getrennt an, und drücken Sie nach jeder Zeile Enter" << endl; for (int i = 0; i < max; i++) { string zeile; cin >> zeile; for (int j = 0; j < max; j++) { Matrix[i][j] = Bruch(zeile); size_t pos = zeile.find(','); zeile = zeile.substr(pos+1); } Ergebnis[i] = Bruch(zeile); } for (int i = 0; i < max; i++) { for (int j = 0; j < max; j++) cout << Matrix[i][j] << "\t"; cout << Ergebnis[i] << endl; } }
Eine mögliche Eingabe wäre jetzt:
(habe das Trennungssymbol durch einen Beistrich ersetzt)
Hoffe das hilft dir weiter.
P.S. Falls du nicht den ganzen Code posten möchtest, dann entferne doch einfach die uninteressanten Stellen. Z.B. das Lösen des Gleichungssystem hat ja nichts mit deiner Frage zu tun.
-
Sorry, mein Handy zeigt mir Teile vom Code falsch an.
Meine Antwort hat dadurch nicht gepasst.
-
-
Ich benutze zur Zeit überhaut keine IDE. Einfach ein ganz normaler Editor.
In den Ferien arbeite ich in einer Firma, wo wir Visual Studio verwenden. Mit dem bin ich ganz zufrieden (und würde damit auch arbeiten, habe aber gerade kein Windows). Visual Studio kann man als Informatikstudent sogar gratis herunterladen (https://www.informatik.tuwien.ac.at/msdnaa).
-
Entweder meine Überlegung ist falsch, oder im Code ist ein offensichtlicher Fehler, den ich nicht sehe, so wie man manchmal den Wald vor lauter Bäumen nicht mehr sieht.
Ich habe ein wenig hinein-gedebuggt und gleich 3 schwere Fehler entdeckt.
Meine Entdeckungen:
1) Das Kriterium i=0 ist natürlich nicht ausschlaggebend dafür, dass man nicht Diagonalisieren kann. Es kann ja sein, dass der maximale Wert in der ersten Zeile (i=0) steht. Abbrechen soll das ganze, wenn val=0 ist.
2) Trotzdem konnte das Programm die Matrix nicht diagonalisieren. Ich habe mir jedes Mal die Matrix ausgegeben, und gesehen, dass in der Schleife bei j=1 nur noch negative Zahlen in der 2. Spalte sehen. Da du nach einem Eintrag suchst, der größer 0 ist, bricht das ganze natürlich ab. Am besten du benutzt die fabs-Funktion. Außerdem kannst du die Abfrage if (Matrix[i][j] != 0) weglassen (stört nicht, bringt aber auch nichts).
Codefor (i = j; i < max; i++) { if (fabs(Matrix[i][j]) > val) { val = fabs(Matrix[i][j]); pos = i; } }
Dazu muss man auch die Mathebibliothek einbinden.Nun konnte das Programm die Matrix diagonalisieren, allerdings gab es noch immer falsche Ergebnisse. Mit weiterem Logging fand ich:
3) Beim Zeilentauschen habe ich die Variable tmp als Integer definiert. Falls in einer zu tauschen Zeile eine Kommazahl steht, wird diese einfach abgeschnitten. Es sollte natürlich
sein.
Ich muss zugeben, dass ich für diesen Fehler verantwortlich bin ;).
Lustig dass dieser Fehler nicht früher aufgetreten ist. Man kann nie genug testen! -
Ja, stimmt.
Stimmt fast. Es werden "die" Zeiger auf die Arrays gelöscht. Matrix ist im Grunde ja ein Array, in dem mehrere Zeiger gespeichert sind. Der erste Zeiger zeigt auf die erste Gleichung, der zweite Zeiger auf die 2. Gleichung, ... Dieses Array wird gelöscht.
-
-
Wahrscheinlich hast du vergessen Ergebnis[0] und Ergebnis[1] zu tauschen:cool:
Kann sein.Jetzt ist der Code schon ein wenig übersichtlicher und auch die Diagonalmatrix stimmt, wenn man z.B. die erste Zeile mit der 3.ten tauscht.
Der Code für's Rückeinsetzen funktioniert aber nur, wenn man wirklich eine Diagonalmatrix hat, sprich die Matrix beginnt in der ersten Zeile mit 0 Nuller, die 2. Zeile beginnt mit 1 Nuller, die 3. mit 2 Nuller, usw. Die Zeilen gehören allerdings noch sortiert. Du kannst dir das leicht überlegen. Beim zurückeinsetzten fängt man ja in der letzten Zeile an (wo alle Faktoren bis auf einen 0 sind) und berechnet die Lösung für die letzte Variable. Dann geht man zur vorletzten Zeile (wo alle bis auf die letzten 2 Faktoren Null sind) und berechnet daraus die Lösung für die vorletzte Variable. Usw.
Ich bin mir nicht sicher, ob dein Code für's Diagonalisieren immer funktioniert. Normalerweise geht man so vor.- Man sucht eine Zeile, bei der die 1. Position ungleich 0 ist. Diese Zeile vertauscht man mit der ersten Zeile. Danach zieht man diese Zeile mit einem geeigneten Faktor von den darunter ab. Damit sichert man sich, dass in der ersten Spalte zuerst ein Element ungleich 0 ist und dann lauter 0er.
- Dann sucht man eine Zeile, die an der 2. Position ungleich 0 ist. (die erste Zeile dürfen wir nicht mehr verwenden). Diese Zeile tauscht man wieder mit der 2. Zeile.
Danach zeiht man diese Zeile von den darunter ab. Jetzt sind die ersten 2 Zeilen und die ersten 2 Spalten in Diagonalgestalt. - Dann sucht man eine Zeile, die an der 3. Position ungleich 0 ist. usw.
Findet man einmal keine geeignete Zeile, so bedeutet dass, das dieses mind. 1 Gleichung linear von den anderen abhängt und man kann diese Matrix nicht diagonalisieren. Es gibt keine eindeutige Lösung.Ich hab mal deinen Code ein wenig umgeschrieben.
Code
Alles anzeigen#include <iostream> using namespace std; int main(int argc, char* argv[]) { // initialisiere Gleichungssystem const int max = 4; float Matrix[max][max]; float Ergebnis[max]; Matrix[0][0] = 1; Matrix[0][1] = 1; Matrix[0][2] = 1; Matrix[0][3] = 1; Ergebnis[0] = 10; Matrix[1][0] = 0; Matrix[1][1] = 2; Matrix[1][2] = 1; Matrix[1][3] = 1; Ergebnis[1] = 11; Matrix[2][0] = 0; Matrix[2][1] = 0; Matrix[2][2] = 1; Matrix[2][3] = 3; Ergebnis[2] = 15; Matrix[3][0] = 0; Matrix[3][1] = 2; Matrix[3][2] = 1; Matrix[3][3] = 4; Ergebnis[3] = 23; //Matrix vor dem Diagonalisieren ausgeben cout << "Matrix vor dem Diagonalisieren" << endl; for (int i = 0; i < max; i++) { for (int a = 0; a < max; a++) cout << Matrix[i][a] << "|"; cout << Ergebnis[i] << endl; } cout << endl; //Matrix diagonalisieren for (int j = 0; j < max; j++) { //Suche Zeile, sodass der Eintrag an der Stelle i != 0 ist. int i = j; while (i < max && Matrix[i][j] == 0) i++; if (i == max) { cout << "Matrix lässt sich nicht diagonalisieren!" << endl; return 0; } if (i != j) // Tausche die Zeilen i und j { int tmp; for (int k = j; k < max; k++) { tmp = Matrix[i][k]; Matrix[i][k] = Matrix[j][k]; Matrix[j][k] = tmp; } tmp = Ergebnis[i]; Ergebnis[i] = Ergebnis[j]; Ergebnis[j] = tmp; } //in der Spalte j 0er erzeugen, indem man die j-te Zeile abzieht for (int m = j + 1; m < max; m++) { if (Matrix[m][j] == 0) continue; float factor = Matrix[m][j] / Matrix[j][j]; Matrix[m][j] = 0; for (int n = j + 1; n < max; n++) Matrix[m][n] -= Matrix[j][n] * factor; Ergebnis[m] -= Ergebnis[j] * factor; } } //Matrix nach dem Diagonalisieren ausgeben cout << "Matrix nach dem Diagonalisieren" << endl; for (int i = 0; i < max; i++) { for (int a = 0; a < max; a++) cout << Matrix[i][a] << "|"; cout << Ergebnis[i] << endl; } cout << endl; //Rückwärtseinsetzten for (int i = max-1; i >= 0; i--) { for (int j = i + 1; j < max; j++) Ergebnis[i] -= Matrix[i][j] * Ergebnis[j]; Ergebnis[i]/= Matrix[i][i]; } //Die Lösungen ausgeben cout << "Lösungen: " << endl; for (int i = 0; i < max; i++) cout << Ergebnis[i] << endl; cin.get(); }
-
Hab nur mal kurz drauf geschaut.
Ich glaub dass es genau umgekehrt ist, dass Diagonalisieren funktioniert nicht, das Rückeinsetzen schon.
Zumindest, wenn ich die erste mit der 2ten Zeile vertausche
dann bekomme ich folgende Diagonalmatrix:Wenn man von der Reihenfolge der Zeilen absieht, ist das zwar eine Diagonalmatrix, allerdings sind die Lösungen dieser Matrix nicht mehr die selben wie bei der ersten.
Wieso suchst du eigentlich in der aktuellen Zeile nach dem ersten Eintrag ungleich Null? Solltest du nicht nach dem erste Eintrag ungleich Null in der Spalte suchen. Schau dir mal diesen PseudoCode an: http://en.wikipedia.org/wiki/Gaussian_elimination#Pseudocode, der gibt dir im Grunde genau vor, was zu tun ist. Anstatt argmax kannst du auch immer die erste Zeile, bei der, der Eintrag ungleich Null ist, nehmen.
Ich werde den Code jetzt nicht näher anschauen, da mich deine Notation ziemlich verwirrt. (Eventuell dich auch.)
Normalerweise speichert man ein Gleichungssystem im Format Matrix[Zeile][Spalte] und nicht Matrix[Spalte][Zeile].