Taschenrechner Punkt vor Strich



  • Du kannst dir ja mal das zur Erklärung ansehen:
    http://de.wikipedia.org/wiki/Polnische_Notation

    Wie man das Programmiertechnisch umsetzt kann ich dir auch nicht sagen, damit habe ich mich nie beschäftigt.



  • Sollte auch nur ein kleiner Tipp sein, keine direkte Lösung für dein Problem. Wenn es dich interessiert, dann google bitte danach. Deinen Riesen-Code kann ich mir momentan aus zeitlichen Gründen wirklich nicht ansehen (muss arbeiten), außerdem beherrsche ich kein C++/CLI (du bist im falschen Forum!).



  • Danke für den.
    Das hab ich nun verstanden, aber ich glaube es würde nicht viel bringen dies einzubinden, im gegenteil es würde den Quelltext warscheinlich noch viel schlimmer machen, glaub ich. 🙂

    Ich habe mir das so überlegt.

    der Anwender gibt jetzt das ein.
    5+5*2

    so jetz müsste ich ja zuerst 5 * 2 rechnen.

    Dies würde ich so rausfiltern und danach +5 rechnen.

    Hört sich leicht an, aber ich krieg das einfach nicht hin.

    Problem ist:

    Der Anwender drückt den Button 5. Noch alles schön
    Dann drückt er den + Button. auch noch ok.
    Jetzt drück er nochman den Button 5. Jetzt machter nix weiter. Wenn der = Button gedrückt wird rechnet er es zusammen. Aber wenn er jetzt den * Button drückt würde er 5*5 rechnen und nach drücken von Button 2 unde dem = Button druck, würde er dann auch * 2 rechnen.
    Das heißt ergebnis = 50 anstatt 15.
    Er Rechnet sozusagen alles nacheinnander und das ist beschissen.^^



  • Dafür benötigst du einen Stack, auf dem du die Zwischenergebnisse speicherst:

    5+5*2=
    
    5    5     15
    +    +
    5    10
    *
    2
    = ->    ->
    
    aber
    
    5*5+2=
    
    5    25   27
    *    +
    5
    + ->
    2    2
    =      ->
    

    Du mußt also bei jeder Operation schauen, welche Priorität der aktuelle im Vergleich zu den vorherigen (auf dem Stack) hat und dann Zwischenergebnisse berechnen.



  • hm ok, Ich hab kein plan über Stacks 😕.
    Toll, naja kann ich ja in nem Toturial kugen. Aber Trodzdem muss ich ja Überprüfen welcher Operator dran ist und wann er dran ist. Kann es sein das ich meine Struktur völlig umstellen muss? Da bei jedem Operatordruck(außer dem ersten)die ersten werte zusammengrechnet werden.

    Nur ich habe keine Ahnung wie ich mit Stacks arbeiten muss. Bin halt noch nicht so weit beim Programmieren.

    Aber danke für die Antwort.

    PS: Heißt Stack sogesehen auf dem Speicher?
    bzw auf dem Speicher bleiben bis das Program beendet wird?



  • Stack ist eine spezielle Datenstruktur:

    http://de.wikipedia.org/wiki/Stapelspeicher



  • da es bei dir nicht auf Effizienz ankommt, hätte ich einfach die Aufgabe als std::string gespeichert, um dann nach einem * (oder auch /) zu suchen, die Werte links und rechts ebenfalls rauszuparsen, diese (Neben)rechnung zu lösen und das Ergebniss mittels Insert wieder an die Stelle im string einzufügen.

    Das gleiche Prinzip lässt sich auch auf Klammerausdrücke anwenden:
    - Klammerausdruck raussuchen
    - ausrechnen
    - Ergebisse wieder einfügen
    - sind keine Klammerausrücke, oder Punktrechnungen mehr enthalten, sind die Additionen und Subtraktionen dran

    Lässt sich sehr gut Rekursiv machen. (Hab ich früher mal in pascal geschrieben, sollte in C++ einfacher sein (hatte damals keine so gut Bibliothek wie std.:string 😉 )

    Bei mir war das damals so eine Funktion wo man die Funktion als String und den einzusetzenden Wert X als real (float) übergeben konnte um beliebige Funktionen grafisch darstellen zu können.

    Also wenn du das nicht jetzt sofort brauchst, kümmer ich mich mal drum wenn ich nachher Feierabend hab. (hätte nämlich Bock sowas auch mal wieder zu coden ^^)



  • Die ganzen Geschichten mit Operatorpräzedenz und Stack und so zielen letzten Endes auf eine Aussage ab: du darfst eine Eingabe nur auswerten, wenn keine darauf folgenden Zeichen das korrekte Ergebnis noch beeinflussen können. Das macht es aber nötig, dass du die Auswertung von (A, Operator, 😎 nicht sofort auf dem button click auswertest, sondern erstmal alle Eingaben speicherst, zum Beispiel in einen String wie oben vorgeschlagen, oder eine Liste, oder was weiß ich.

    Beispiel 1:
    Eingabe: "1 + 1 + 1 ="
    Schritt für Schritt wird dies ausgewertet zu 2+1 und schließlich 3. Dies ist aber NUR zulässig, weil nach dem "1+1" ein weiteres "+" kommt, was gleiche oder niedrigere Priorität wie das erste "+" hat (ist ja beides plus, also gilt in diesem Fall Assoziativität, d.h. a+b+c = (a+b)+c = a+(b+c) ).

    Beispiel 2:
    Eingabe: "2 + 5 * 5 ="
    Wenn du mit parsen (also einlesen) deines Eingabestrings bei "2+5" angekommen bist, darfst du diese erst auswerten, wenn hintenan keine "stärker bindender" (punkt vor strich, potenz vor produkt, klammer vor allem anderen, etc.) Operator mehr steht.

    Du musst also bis hierhin parsen "2 + 5 * ". An diesem Punkt merkst du "oha, punkt hat höhere prezedenz als plus". An dieser Stelle merkst du dir das "2 +" erstmal und parst weiter, um den enger bindenden Ausdruck zuerst zu berechnen. Wenn dieser fertig ist (kein NOCH enger bindender Operator hinter dem 5*5, wie es zum Beispiel bei 5*5^2 der Fall wäre), wertest du ihn aus. Wenn du das 5*5 = 25 ausgewertet hast, gehst du zurück zu dem Ausdruck 2 + (Ergebnis von 5*5) und wertest diesen aus.

    Taschenrechner mit Punkt vor Strich ist kompliziert genug, dass man so Sachen machen muss. Einfach nur "klick - auswert - klick - auswert" geht auf jeden Fall schief, weil es keine Operatorpräzedenz berücksichtigen kann.



  • Ich meine es so:

    1. Formel komplett einlesen -> std::string

    Rekursive Funktion
    {
    Finde alle Potenzierungen im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Multiplikationen im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Klammerausdrücke im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Subtraktionen im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Additionen im String -> Ausrechnen & Ergebniss einfügen

    }

    damit müsstest du auf der sicheren seite sein, da du die wichtigen Dinge zuerst auswertest.


  • Mod

    Kann mir einer erklären, warum das hier im falschen Forum ist bzw. noch niemand darauf hingewiesen hat?



  • _matze schrieb:

    ...außerdem beherrsche ich kein C++/CLI (du bist im falschen Forum!).



  • hab mich schon gewundert warum der Quelltext so komisch aussieht 🕶



  • Finde ich in dem Fall aber gar nicht schlimm, da die Diskussion ja eher sprachenunabhängig verläuft.



  • It0101 schrieb:

    Rekursive Funktion
    {
    Finde alle Potenzierungen im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Multiplikationen im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Klammerausdrücke im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Subtraktionen im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Additionen im String -> Ausrechnen & Ergebniss einfügen

    }

    Moin,

    wiso hast du eigentlich die Multiplikation/Division vor die Klammernbearbeitung gesetzt?
    Wenn man z.B. solch einen Ausdruck "2*(5+5)" vorzuliegen hat und du dann als erstest die Multiplikation auflösen willst, soll das Programm 2*( ausrechnen, aber das geht schlecht, dann müsste man das ganze abfangen und dann zunächst einmal die Klammer auflösen. Ergo wäre es doch eigentlich unkomplizierter, wenn man erst die Klammern auflöst "5+5=10" und dann die Multiplikation durchführt "10*2=20".



  • ups sry, my fault ^^ Hatte da in dem Moment nicht so genau drüber nachgedacht 😉

    Der ganze Klammerkram muss natürlich nach oben.



  • ahhh ich hab aber auch nicht aufgepasst 🤡
    Klammernbehandlung muss ja an die erste Stelle, z.B. 2^(5-2)

    Rekursive Funktion
    {
    Finde alle Klammerausdrücke im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Potenzierungen im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Multiplikationen im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Subtraktionen im String -> Ausrechnen & Ergebniss einfügen
    Finde alle Additionen im String -> Ausrechnen & Ergebniss einfügen
    }
    


  • da hast du wohl recht, auch wenn es in dem Fall egal ist, da der Threadersteller ja nur Grundrechenarten benötigt 😉


Anmelden zum Antworten