Die Idee hatte ich zuerst auch, aber es wird ja immer tmp eingelesen. Wenn es jetzt keinen Bruchstrich gibt, gibt es auch kein Nenner, tmp ist also immer das nächste Zeichen des istream. Es wird also immer das nächste Zeichen des darauffolgenden Bruches eingelesen, oder sehe ich das falsch?
Beiträge von henriknikolas
-
-
Kann mit keiner helfen? Ich möchte nur dass man bei meiner Bruch Klasse auch zahlen wie 1, 2 ...eingeben kann
-
Tut mir Leid, dass ich jetzt erst antworte, aber diese Woche hatte ich sehr viel mit der Schule zu tun, deshalb bin ich gar nicht zum Programmieren gekommen. Ich habe jetzt meine Funktion zum Einlesen etwas verändert, mit den Brüchen einlesen klappt alles wunderbar, nur kann ich jetzt nur Brüche wie 1/2 eingeben und keineZahlen wie 3 oder 0.5. Kannst du mir vielleicht dafür noch einen Tipp geben?!?
-
Ich hab mir jetzt mal eine Klasse zur Bruchrechnung gebastelt, weil die Rechnungen mit Brüchen ja genauer sind. Wenn ich jetzt eine Instanz dieser Klasse erstelle, kann ich Rechnen, die Werte über >> einlesen und über << ausgeben, halt wie auf Papier und so weiter...
Allerdings funktioniert das Einlesen mit meinem 2-dimensionalen dynamischen Array irgendwie nicht, aber ohne Array funktioniert es. Ich habe im Hauptquellcode einfach alle float durch Bruch, das ist die Klasse für die Bruchrechung ersetzt. Ich schreibe hier nur die Methode fürs Einlesen und die der Hauptdatei, sonst wäre es viel zu lange. Wenn du die ganze Klasse brauchst, kann ich sie dir gerne schicken:C
Alles anzeigen#include <iostream> #include <math> #include <conio> #include "Bruch.h" using namespace std; int main(int argc, char* argv[]) { int number; cout << "Bitte geben Sie die Anzahl der Gleichungen an: "; cin >> number; const int max = number; //Dynamische Array von Zeigern anlegen: Bruch** Matrix = new Bruch*[max]; //An jeden Zeiger ein Array hängen for (int i = 0; i < max ; i++) Matrix[i] = new Bruch[max]; Bruch *Ergebnis = new Bruch[max]; cout << "Bitte geben Sie alle Koeffizienten durch ein Leerzeichen getrennt an, und drücken Sie nach jeder Zeile Enter" << endl; //Koeffizienten einlesen for (int i = 0; i < max; i++) for (int j = 0; j <= max; j++) { if (j != max) cin >> Matrix[i][j]; else cin >> Ergebnis[i]; } //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++) { int pos = 0, i = 0; Bruch val= 0; for (i = j; i < max; i++) { if (Matrix[i][j].to_double() != 0) if (fabs((Matrix[i][j].to_double())) > (val.to_double())) { val = fabs(Matrix[i][j].to_double()); pos = i; } } i = pos; if (val == 0) return 0; if (i != j) // Tausche die Zeilen i und j { Bruch 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; Bruch 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; for (int i = 0; i < max; i++) delete [] Matrix[i]; delete [] Matrix; delete Ergebnis; getch();
Code
Alles anzeigen//Ein- und Ausgabe istream& operator>>(istream &s, Bruch &b) { string str; stringstream ostr; int pos1 = 0, pos2 = 0; char tmp; long long zaehler, nenner; getline(s, str); //Den istream in den String str kopieren while(pos1 != -1 || pos2 != -1) //Alle Klammern aus dem String entfernen { pos1 = str.find("("); if (pos1 >= 0)str.erase(pos1, pos1+1); pos2 = str.find(")"); if (pos2 >= 0)str.erase(pos2, pos2+1); } ostr << str; //Dem stringstream den String str hinzufügen ostr >> zaehler; //Die erste Zahl aus dem Stream ist der Zähler ostr >> tmp; if(tmp == '/') //Wenn das nächste Zeichen ein / ist, auch noch den Nenner einlesen { ostr >> nenner; b = Bruch(zaehler, nenner); return s; } else //Sonst ist der Nenner 1; { nenner = 1; b = Bruch(zaehler, 1); return s; } s.setstate(std::ios_base::failbit); //Ein Fehler ist beim Einlesen aufgetreten return s; } ostream& operator<<(ostream &s, Bruch b) { s << b.getZaehler() << "/" << b.getNenner(); return s; }
-
Ich bin leider kein Informatikstudent, sondern erst in der 9. Klasse:mad:, aber ich lad mir mal eine Testversion von chip herunter und probiere es aus. Ich nehme mal an, du verwendest Linux und g++, nicht?
-
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!
So hab jetzt alle Sachen verändert und siehe da, wer hätte es gedacht es funktioniert. Ich hab die Aufgabe gleich bei einem Onlineprogramm eingegeben und die Lösungen stimmten überein!!! -
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!
So hab jetzt alle Sachen verändert und siehe da, wer hätte es gedacht es funktioniert. Ich hab die gleiche Aufgabe bei einem Onlineprogram zum lösen eingegeben, und die Ergebnisse stimmten überein!!! -
Super vielen Dank, das mit dem int hab ich gar nicht gesehen, obwohl ich mir ganz viele Stellen markiert und mit Kommentaren versehen hatte, hab wohl doch zu oberflächlich gelesen. Mit dem Betrag ist es logisch, da hab ich zu beschränkt gedacht, genauso mit dem Kriterium i = 0, das war husch husch hätte ich eigentlich auch selber drauf kommen können:mad:
Vielen vielen Dank nochmals, ich benutze zur Zeit Borland C++ Builder 6, welche IDE benutzt du, ich hab mir mal Dev-C++ angeschaut, das war auch ganz gut, fand ich am Anfang aber ein bisschen unübersichtlich, kannst du mir vielleicht noch was empfehlen? -
Ich hab jetzt ein bisschen noch am Code rumgebastelt, weil ich gelesen habe, dass man beim Zeilentauschen die Zeile mit dem größten Wert für Matrix[i][j] suchen soll, und die dann zum tauschen verwenden soll:
Code
Alles anzeigenfor (int j = 0; j < max; j++) { . . . // größtes Element in der Spalte j suchen, dass ungleich 0 ist int pos = 0, i = 0; float val= 0; for (i = j; i < max; i++) { if (Matrix[i][j] != 0) if (Matrix[i][j] > val) { val = Matrix[i][j]; pos = i; } } i = pos; if (i == 0) { cout << "Matrix lässt sich nicht diagonalisieren!" << endl; return 0; } . . . }
Das klappt aber nicht immer, zum Beispiel beim folgenden Gleichungssystem nicht:
2 4 2 1 2
3 -3 1 0 -6
1 1 -2 0 8
4 -2 3 6 -10
In der letzten Zeile steht als Koeffizient nach dem Diagonalisieren eine 0, das ergibt logischerweise einen Fehler. Wenn ich das Gleichungssystem allerdings so diagonalisiere, dass das erste Vorkommen von Matrix[i][j] != 0 verwendet wird, so wie du es gemacht hast, so klappt das Lösen ohne Probleme. 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. -
Wenn man bei Google nach linearen Gleichungssystemen sucht findet man auch schnell das Wort Pivotisierung. Das ist doch das Zeilen vertauschen. Damit man das Gleichungssystem lösen kann oder damit die Ergebnisse genauer sind? Ich weiß über Gleichungssysteme nur aus dem letzten Schuljahr bescheid, als ich in der 8. Klasse war, deshalb frage ich lieber hier.
-
Mit diesen Anweisungen werden die Arrays gelöscht, auf die der Zeiger zeigt, nicht?
Und hier wird der Zeiger auf die Arrays gelöscht
Nur so, ob ich es verstanden habe, weil das mit den dynamischen mehrdimensionalen Arrays mir neu ist -
Hab jetzt noch die Option eingefügt, dass man ein eigenes Gleichungssystem eingeben kann, mit dem 2 dimensionalem dynamischen Array war es etwas kompliziert. Jetzt muss ich nur noch die Eingaben überprüfen, dass da nichts falsches eingegeben wird. Vielen vielen Dank nochmals
Code
Alles anzeigen#include <iostream> using namespace std; int main(int argc, char* argv[]) { int number; cout << "Bitte geben Sie die Anzahl der Gleichungen an: "; cin >> number; const int max = number; //Dynamische Array von Zeigern anlegen: float** Matrix = new float*[max]; //An jeden Zeiger ein Array hängen for (int i = 0; i < max ; i++) Matrix[i] = new float[max]; float *Ergebnis = new float[max]; cout << "Bitte geben Sie alle Koeffizienten durch ein Leerzeichen getrennt an, und drücken Sie nach jeder Zeile Enter" << endl; //Koeffizienten einlesen for (int i = 0; i < max; i++) for (int j = 0; j <= max; j++) { if (j != max) cin >> Matrix[i][j]; else cin >> Ergebnis[i]; } //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(); cin.get(); }//------------------------------------------------------------------
-
Stimmt, du hast volkommen Recht mit deiner Vorgehensweise. Es klingt auch sehr viel logischer als meins:engel:
Auf jeden Fall funktioniert alles, wenn ich die Zeilen ändere. Vielen Dank nochmal.Ich werd das ganze dann noch mal auf vector ausbauen, dann kann ich (fast) beliebig große Gleichungssysteme einlesen -
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:
So hab das jetzt mal gemacht und hab das folgende Ergebnis raus:
0|2|1|1|11
1|0|0.5|0.5|4.5
0|0|1|3|15
0|0|0|3|12
Wahrscheinlich hast du vergessen Ergebnis[0] und Ergebnis[1] zu tauschen:cool: -
So ich hab das mit der Matrix[Zeile][Spalte] geändert. Hatte Mathe und C++ einfach ein bisschen durcheinander gewürfelt. Jetzt kommt man auf das gleiche Ergebnis. Ich versuch den Pseudocode auf Wikipedia mal zu verstehen, leider ist der ja auf Englisch. Meine Idee war bis jetzt das man immer eine Zeile setzt und die von den darunterliegenden abzieht, sodass eine Variable in der Zeile 0 wird. Dafür muss man den Quotienten der beiden Zeilen für die Variable, die eliminiert werden soll, bilden. Wenn das aber eine DIvision durch 0 ergibt... deshalb hab ich überprüft ob der Divisor 0 ist, ist jetzt auch schwer zu erklären.
-
Hallo, ich hoffe ihr könnt mir helfen. Ich möchte lineare Gleichungssysteme lösen. Die Umformung zur Diagonalform war nicht sonderlich schwer und klappt perfekt. Nur mit dem Rückwärtseinsetzten hapert es. Wenn ich beispielsweise 2 Zeilen vertausche kommen andere Werte raus. Könnt ihr mir helfen wie ich das auch noch schaffe. Ach ja, tut mir Leid, dass der Code etwas unstrukturiert ist, nachher schreibe ich auch noch eine Klasse... ich wollte mich nur erstmal mit den inhaltlichen Problemen auseinandersetzten:shiner:
C
Alles anzeigen//--------------------------------------------------------------------------- #pragma hdrstop #include <iostream> #include <conio> #include <vector> using namespace std; //--------------------------------------------------------------------------- float Matrix[4][4]; float Ergebnis[4]; #pragma argsused int main(int argc, char* argv[]) { int max = 4; Matrix[0][0] = 1; Matrix[0][1] = 1; Matrix[0][2] = 1; Matrix[0][3] = 1; Matrix[1][0] = 0; Matrix[1][1] = 2; Matrix[1][2] = 1; Matrix[1][3] = 1; Matrix[2][0] = 0; Matrix[2][1] = 0; Matrix[2][2] = 1; Matrix[2][3] = 3; Matrix[3][0] = 0; Matrix[3][1] = 2; Matrix[3][2] = 1; Matrix[3][3] = 4; Ergebnis[0] = 10; Ergebnis[1] = 11; Ergebnis[2] = 15; Ergebnis[3] = 23; for (int i = 0; i < max; i++) //Matrix Diagonalisieren { for (int j = i+1; j < max; j++) { int b = 0; for (b = 0; b < max; b++) // in der aktuellen Zeile den ersten Wert, der ungleich 0 ist finden if (Matrix[i][b] != 0) break; if (Matrix[i][b] == 0)continue; float faktor = Matrix[j][b]/Matrix[i][b]; for (int a = 0; a < max; a++) Matrix[j][a] -= Matrix[i][a] * faktor; // aktuelle Gleichung von den anderen abziehen Ergebnis[j]-=Ergebnis[i]*faktor; } } for (int i = 0; i < max; i++) //Matrix nach dem Diagonalisieren ausgeben { for (int a = 0; a < max; a++) cout << Matrix[i][a] << "|"; cout << Ergebnis[i] << endl; } for (int i = max-1; i >= 0; i--) //Rückwärtseinsetzten { for (int j = i + 1; j < max; j++) { Ergebnis[i] -= Matrix[i][j] * Ergebnis[j]; } if (Matrix[i][i] == 0) continue; Ergebnis[i]/= Matrix[i][i]; } for (int i = 0; i < max; i++) //Die Lösungen ausgeben cout << Ergebnis[i] << endl; cin.get(); } //---------------------------------------------------------------------------