1. Dashboard
  2. Forum
    1. Unerledigte Themen
  3. Mitglieder
    1. Letzte Aktivitäten
    2. Benutzer online
    3. Team-Mitglieder
    4. Trophäen
    5. Mitgliedersuche
  4. Tutorial Bereich
  • Deutsch
  • Anmelden
  • Registrieren
  • Suche
Dieses Thema
  1. Informatik Forum
  2. Webmaster & Internet
  3. Entwicklung

C++ lineare Gleichungssysteme lösen

  • henriknikolas
  • 8. März 2014 um 20:26
  • Unerledigt
  • 1
  • 2
  • henriknikolas
    5
    henriknikolas
    Mitglied
    Punkte
    195
    Beiträge
    36
    • 8. März 2014 um 20:26
    • #1

    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
    //---------------------------------------------------------------------------
    
    
    
    
    #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();
    }
    //---------------------------------------------------------------------------
    Alles anzeigen

    Einmal editiert, zuletzt von henriknikolas (9. März 2014 um 09:47)

  • Jakube
    3
    Jakube
    Mitglied
    Reaktionen
    4
    Punkte
    64
    Beiträge
    12
    • 8. März 2014 um 23:40
    • #2

    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

    Code
    Matrix vor Diagonalisieren
    0|0|1|3|10
    0|2|1|1|11
    1|1|1|1|15
     0|2|1|4|23


    dann bekomme ich folgende Diagonalmatrix:

    Code
    0|0|1|3|10
    0|2|0|-2|1
    1|0|0|-1|4.5
    0|0|0|3|12

    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].

  • henriknikolas
    5
    henriknikolas
    Mitglied
    Punkte
    195
    Beiträge
    36
    • 9. März 2014 um 09:54
    • #3

    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.

  • henriknikolas
    5
    henriknikolas
    Mitglied
    Punkte
    195
    Beiträge
    36
    • 9. März 2014 um 13:42
    • #4
    Zitat von Jakube

    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

    Code
    Matrix vor Diagonalisieren
    0|0|1|3|10
    0|2|1|1|11
    1|1|1|1|15
     0|2|1|4|23


    dann bekomme ich folgende Diagonalmatrix:

    Code
    0|0|1|3|10
    0|2|0|-2|1
    1|0|0|-1|4.5
    0|0|0|3|12


    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:

  • Jakube
    3
    Jakube
    Mitglied
    Reaktionen
    4
    Punkte
    64
    Beiträge
    12
    • 9. März 2014 um 13:50
    • #5
    Zitat von henriknikolas

    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
    #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();
    }
    Alles anzeigen

    Einmal editiert, zuletzt von Jakube (9. März 2014 um 13:52)

  • henriknikolas
    5
    henriknikolas
    Mitglied
    Punkte
    195
    Beiträge
    36
    • 9. März 2014 um 16:51
    • #6

    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

  • henriknikolas
    5
    henriknikolas
    Mitglied
    Punkte
    195
    Beiträge
    36
    • 9. März 2014 um 17:17
    • #7

    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
    #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();
    }//------------------------------------------------------------------
    Alles anzeigen
  • Jakube
    3
    Jakube
    Mitglied
    Reaktionen
    4
    Punkte
    64
    Beiträge
    12
    • 9. März 2014 um 19:13
    • #8

    Am Schluss musst du noch die Matrix und den Ergebnis Vektor löschen.
    Also in etwa so

    Code
    for (int i = 0; i < max; i++)
       delete [] Matrix[i];
    delete [] Matrix;
    delete Ergebnis;
  • henriknikolas
    5
    henriknikolas
    Mitglied
    Punkte
    195
    Beiträge
    36
    • 9. März 2014 um 19:52
    • #9
    Code
    for (int i = 0; i < max; i++)
       delete [] Matrix[i];


    Mit diesen Anweisungen werden die Arrays gelöscht, auf die der Zeiger zeigt, nicht?

    Code
    delete [] Matrix;


    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

  • Jakube
    3
    Jakube
    Mitglied
    Reaktionen
    4
    Punkte
    64
    Beiträge
    12
    • 9. März 2014 um 20:27
    • #10
    Zitat von henriknikolas
    Code
    for (int i = 0; i < max; i++)
       delete [] Matrix[i];


    Mit diesen Anweisungen werden die Arrays gelöscht, auf die der Zeiger zeigt, nicht?

    Ja, stimmt.

    Zitat von henriknikolas
    Code
    delete [] Matrix;


    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

    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.

  • henriknikolas
    5
    henriknikolas
    Mitglied
    Punkte
    195
    Beiträge
    36
    • 10. März 2014 um 20:31
    • #11

    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.

  • henriknikolas
    5
    henriknikolas
    Mitglied
    Punkte
    195
    Beiträge
    36
    • 11. März 2014 um 18:46
    • #12

    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
    for (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;
                    }
                    .
                    .
                    .
               }
    Alles anzeigen


    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.

  • Jakube
    3
    Jakube
    Mitglied
    Reaktionen
    4
    Punkte
    64
    Beiträge
    12
    • 11. März 2014 um 20:13
    • #13
    Zitat von henriknikolas

    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).

    Code
    for (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.

    Code
    #include <math.h>


    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

    Code
    float tmp;

    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!

  • henriknikolas
    5
    henriknikolas
    Mitglied
    Punkte
    195
    Beiträge
    36
    • 11. März 2014 um 21:13
    • #14

    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?

  • Jakube
    3
    Jakube
    Mitglied
    Reaktionen
    4
    Punkte
    64
    Beiträge
    12
    • 11. März 2014 um 21:25
    • #15

    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).

  • henriknikolas
    5
    henriknikolas
    Mitglied
    Punkte
    195
    Beiträge
    36
    • 11. März 2014 um 21:32
    • #16
    Zitat von Jakube

    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).

    Code
    for (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.

    Code
    #include <math.h>


    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

    Code
    float tmp;

    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!

    Alles anzeigen


    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!!!

  • henriknikolas
    5
    henriknikolas
    Mitglied
    Punkte
    195
    Beiträge
    36
    • 11. März 2014 um 21:33
    • #17
    Zitat von Jakube

    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).

    Code
    for (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.

    Code
    #include <math.h>


    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

    Code
    float tmp;

    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!

    Alles anzeigen


    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!!!

  • henriknikolas
    5
    henriknikolas
    Mitglied
    Punkte
    195
    Beiträge
    36
    • 11. März 2014 um 21:41
    • #18

    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?

    2 Mal editiert, zuletzt von henriknikolas (11. März 2014 um 21:45)

  • Jakube
    3
    Jakube
    Mitglied
    Reaktionen
    4
    Punkte
    64
    Beiträge
    12
    • 11. März 2014 um 22:57
    • #19

    jep

  • henriknikolas
    5
    henriknikolas
    Mitglied
    Punkte
    195
    Beiträge
    36
    • 16. März 2014 um 17:03
    • #20

    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
    #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();
    Alles anzeigen
    Code
    //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;
    }
    Alles anzeigen
    • 1
    • 2

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!

Benutzerkonto erstellen Anmelden

Benutzer online in diesem Thema

  • 1 Besucher

Rechtliches

Impressum

Datenschutzerklärung

  • Alles
  • Dieses Thema
  • Dieses Forum
  • Seiten
  • Forum
  • Lexikon
  • Erweiterte Suche
  • Deutsch
  • English
Zitat speichern