Einfache funktionsgleichungssystem - moeglich?



  • hallo,

    ich programmiere jetzt seit einigen jahren C, kann also etwas in C.

    nun moechte ich zum ersten mal etwas mathematisch angehauchtes programmieren und frage daher euch mal:

    und zwar moechte ich ein programm schreiben, das gleichungssysteme (matrizen, vektoren, diese richtung) loesen kann. halt sowas zb
    (die hochzeichen bitte als indizes ansehen)

    3x¹ + 4x² +7x³ = 9
    2x¹ + 3x² +5x³ = 5
    5x¹ + 2x² + 3x³ = 4

    nun moehcte mann x¹ x² und x³ ausrechnen. auf blatt und papier ist das klar, aber wie macht man sowas mit einer programmiersprache (in C)? habe garkeinen ansatzpunkt, koennt ihr mir ein wenig helfen, evtl mit pseudo code oder evtl hat jemand sowas schonma gemacht?

    spaeter soll das programm so aussehen das es fuer billig grosse matrizen, vektoren... also beliebig grosse gleichungssysteme die sache ausrechnen kann

    hoffe ihr koennt mir dazu was sagen und etwas helfen

    danke



  • Hallo,

    vor zwei Wochen hab ich mal versucht, so ein Programm zu machen. Ist leider noch etwas verbuggt (kann auch daran liegen, dass ich mich erst fünf Stunden damit beschäftigt hab) und besonders schönes OOP ist es auch nicht.

    Ich hab für jede Gleichung ein Objekt angelegt mit drei Bruch-Objekten (dachte mir, ich könnt gleich noch ne Bruchklasse dazu machen) für x1, x2 und x3, drei char-Objekten (weil man die bei mir auch noch benennen kann wie man will) und dem Ergebnis.

    Wenn du weißt, wie dus aufm Blatt Papier machen würdest, dann sag dem Computer jetzt mal ganz genau, wie du immer vorgehst. Ich habs nach dem Gaußalgorithmus getan. Ich würde anfangs auf Tricks verzichten, die das Rechnen per Hand erleichtern, und wirklich immer nach Schema F vorgehen. Die Tricks kannst du nachher ja noch einbauen.



  • Ich habe vor einiger Zeit mal sowas gemacht. Wenn Du C einigermaßen kannst, ist das meiner Meinung eigentlich gar nicht so schwer. Im Prinzip musst Du Dir nur ganz genau angucken, was Du machst, wenn Du ein Gleichungssystem auf dem Papier löst und das dann verallgemeinert auf den Computer übertragen. Wenn Du Dich z.B. an dieses Dreiecksschema (Gauss-Verfahren?) hälst, ist das zwar bestimmt im Vergleich zu effizienten computergstützten Lösungsverfahren ziemlich hässlich und langsam, aber es funktioniert und ist, da das Verfahren Dir ja vorgibt, wie DU das System zu lösen hast, nicht so schwer zu implementieren.

    P.S.: Ich bin einfach zu langsam für diese Welt...



  • hallo

    erstmal danke fuer die flotten antworten

    @Michael E.
    also OOP kann ich nicht/mag ich nicht so 😉

    dein vorgehen macht sinn, aber danach wuerde ich immer noch vor simplen problemen stehen, dazu gleich mehr

    @Asgard
    ja genau so hatte ich das auch vor; es sollte erstmal eine ganz simple variante werden damit ich mir das angucken konnte wie sowas laeuft, aber eben das umsetzen faellt mir irgendwie schwer

    3x¹ + 4x² +7x³ = 9
    2x¹ + 3x² +5x³ = 5
    5x¹ + 2x² + 3x³ = 4

    sagen wir ich moehcte im ersten schritt die 2. zeile so veraendern, das vor x¹ eine null steht. dann wuerde ich die obere gleichung mal 2 nehmen und die 2. zeile mal -3; die beiden zeilen addiert wuerde fuer die 2. zeile eine 0 vor dem x¹ ergeben

    dafuer muesste man jetzt eine funktion fuer das programm schreiben, die das irgendwie erledigt. aber wie? ich koennte ja die sachen durchrechnen lassen und gucken ob 0 rauskommt, was fuer kleine und einfache sachen gehen mag, aber bei 1000 feldern ohne runde zahlen wird das sehr ineffizient, wenn es ueberhaupt eine loesung bringt.



  • Sagen wir mal, die ersten Vorfaktoren der Gleichungen heissen a,b,c (in Deinem Beispiel wäre a = 3, b = 2, c = 5).
    Du willst Zeile 1 erhalten und in Zeilen 2 und 3 eine 0 konstruieren. Allgemein kannst Du das so lösen:
    Du multipliziert die Zeilen 2 und 3 mit a. Dann ziehst Du von Zeile 2 b-mal Zeile 1 und von Zeile 3 c-mal Zeile 1 ab. Dann hast Du auf jeden Fall zwei Nullen in der Spalte. Das kannst Du vom Prinzip her so weitermachen, bis Du das komplette Gleichungssystem gelöst hast.

    Wie gesagt, es ist sicher nicht besonders effektiv und es kann sein, dass bei 1000 Feldern Probleme auftreten - ich habs noch nie probiert. Aber bei 1000 Feldern würde ich generell mal behaupten, dass das dann auch keine "Einsteiger-Übung" mehr ist.



  • Ich hab das Ganze etwas anders in der Schule gelernt. Ich versuch, b und c gleich -a zu machen und dann IIa = I+II und IIIa = I + III zu rechnen. Ist IMHO einfacher und so weit ich das auf die Schnelle beurteilen kann, läuft es auch schneller.



  • DAS Standard-Verfahren zur Lösung linearer Gleichungssysteme:

    http://de.wikipedia.org/wiki/Gau%C3%9Fsches_Eliminationsverfahren



  • Bei nichtlinearen Gleichungssystemen ist es schwieriger, da approximiert man meist numerisch. Aber ich denke, dass du die Indizes nur unglücklich positioniert hast. Die sehen aus wie Exponenten. Habe neulich einige Zerlegungen in meine Matrixklasse eingebaut. Wenn du willst kann ich mal ein wenig Code posten.



  • @Michael E.: Und wie kommst Du dann (im gegebenen Beispiel) z.B. in der zweiten Zeile auf -a?

    @Mastah: Jo, er hat im ersten Posting geschrieben, dass das Indizes sind.



  • b * (-a/b) = -a



  • Dürfte aber IMHO auch was Geschwindigkeit angeht aufs selbe rauslaufen:
    Bei Dir errechnet sich z.B. der neue zweite Vorfaktor der zweiten Zeile (b2, die ersten aller Zeilen sollen jetzt mal a1, b1, c1 heissen) aus
    b2_neu = b2 * (-a) / b + a2. Bei mir ists b2_neu = b2 * a - b * a2.



  • Ich weiß nicht, was du da machst, aber ich rechne b2_neu genau so aus wie b1_neu.



  • Naja, wenn Du b1_neu = -a1 haben willst, wie Du gesagt hast, wirst Du wohl die ganze Zeile mit -a/b1 multiplizieren, oder? Also steht dann in der zweiten Zeile -a (b2* (-a)/b) (b3*(-a)/b). Dann addierst Du I+II und dann steht da 0 (b2*(-a)/b+a2) (b3*(-a)/b+a3), wobei dann (b2*(-a)/b+a2) das neue b2 ist, mit dem weitergerechnet werden muss.
    Oder anders, bevor das sinnlos ausufert: Wo siehst Du den Geschwindigkeitvorteil bei Dir? Ich sehe ihn nicht und würde ihn gerne verstehen, da beides IMHO aufs selbe rauskommt.



  • Ich bin zwar wirklich kein guter Mathematiker, aber ich versuchs jetzt mal:

    Ich schreibe nur Varablen für die Werte hin, die gegeben sind. Meine LaTeX-Kenntnisse sind sehr beschränkt, deshalb siehts auch nicht sonderlich toll aus. Zuerst meine Methode:

    $x\_1 + y\_1 + z\_1 = e\_1$ zwei Rechenschritte \\ \\ $x\_2 + y\_2 + z\_2 = e\_2$ \\ $-x\_1 - \frac{x\_1 y\_2}{x\_2} = \frac{x\_1 e\_2}{x_2}$ \\ $y\_1 + z\_1 - \frac{x\_1 (y\_2 + z\_2)}{x\_2} = \frac{x\_1 e\_2}{x\_2} + e\_1$ acht Rechenschritte \\ \\ $x\_3 + y\_3 + z\_3 = e\_3$ \\ $-x\_1 - \frac{x\_1 y\_3}{x\_3} = \frac{x\_1 e\_3}{x_3}$ \\ $y\_1 + z\_1 - \frac{x\_1 (y\_3 + z\_3)}{x\_3} = \frac{x\_1 e\_3}{x\_3} + e\_1$ \\ $\- \frac{y\_1 y\_2}{y\_3} - \frac{z\_1 y\_2}{y\_3} + \frac{(x\_1 + y\_2)(y\_3 + z\_3)}{x\_3 y\_3} = - \frac{x\_1 y\_2 e\_3}{x\_3 y\_3} - \frac{e\_1 y\_2}{y\_3}$ \\ $\- y\_1 y\_2 - z\_1 y\_2 + \frac{(x\_1 + y\_2)(y\_3 + z\_3)}{x\_3} = - \frac{x\_1 y\_2 e\_3}{x\_3} - e\_1 y_2$ \\ $\- y\_2 (y\_1 + z\_1) + \frac{(x\_1 + y\_2)(y\_3 + z\_3)}{x\_3} = - \frac{x\_1 y\_2 e\_3}{x\_3} - e\_1 y\_2$ \\ $y\_1 + z\_1 - \frac{x\_1 (y\_2 + z\_2)}{x\_2} - y\_2 (y\_1 + z\_1) - y\_2 z\_1 + \frac{(x\_1 + y\_2) (y\_3 + z\_3)}{x\_3} = \frac{x\_1 e\_2}{x\_2} + e\_1 + \frac{x\_1 y\_1 e\_3}{x\_3} - e\_1 y\_2$ vierundzwanzig Rechenschritte \end{math}

    2 + 8 + 24 + 3 (weil man noch rechte Seite durch linke Seite rechnet) ergeben 37 Rechenschritte.

    Jetzt deine Methode:

    \begin{math} $x\_1 + y\_1 + z\_1 = e\_1$ zwei Rechenschritte \\ \\ $x\_2 + y\_2 + z\_2 = e\_2$ $x\_1 (x\_2 + y\_2 + z\_2) = x\_1 e\_2$ \\ $x\_1 (x\_2 + y\_2 + z\_2) - x\_2(x\_1 + y\_1 + z\_1) = x\_1 e\_2 - x\_2 e\_1$ zehn Rechenschritte \\ \\ $x\_3 + y\_3 + z\_3 = e\_3$ $x\_1 (x\_3 + y\_3 + z\_3) = x\_1 e\_3$ \\ $x\_1 (x\_3 + y\_3 + z\_3) - x\_3(x\_1 + y\_1 + z\_1) = x\_1 e\_3 - x\_2 e\_3$ \\ $y\_2 (x\_1 (x\_3 + y\_3 + z\_3) - x\_3 (x\_1 + y\_1 + z\_1) ) = y\_2 (x\_1 e\_3 - x\_3 e\_1)$ \\ $y\_2 (x\_1 (x\_3 + y\_3 + z\_3) - x\_3 (x\_1 + y\_1 + z\_1) ) - y\_3 (x\_1 (x\_2 + y\_2 + z\_2) - x\_2(x\_1 + y\_1 + z\_1) ) = y\_2 (x\_1 e\_3 - x\_3 e\_1) - y\_3 (x\_1 e\_2 - x\_2 e\_1)$ sechsundzwanzig Rechenschritte \end{math}

    2 + 10 + 28 + 3 ergeben 41 Rechenschritte. Also ist mein Weg der schnellere.

    Alles ohne jegliches Gewähr.



  • Ich habs mir jetzt gerade auch mal was genauer angeschaut (hätte ich vielleicht besser mal direkt gemacht) und komme zwar auf eine etwas andere Anzahl Rechenschritte (kann auch daran liegen, dass ich mir nicht 100% sicher bin, ob ich Deine Darstellung richtig verstanden habe), aber Du hast in jedem Fall recht - Deine Methode ist wirklich schneller. Ich war irgendwie so auf den Vergleich von einer einzigen Teilrechnung fixiert (=engstirnig 😃 ), dass ich nicht gesehen hab, dass Deine insgesamt doch besser ist.


Anmelden zum Antworten