Du verwendest einen veralteten Browser. Es ist möglich, dass diese oder andere Websites nicht korrekt angezeigt werden. Du solltest ein Upgrade durchführen oder ein alternativer Browser verwenden.
ich programmiere der Zeit einen Taschenrechner. Alls funktoniniert ich bin auch kein Anfänger sondern eher momentan etwas Ratlos und zwar zu meiner Frage: 5+5 ausrechnen zu lassen ist ja total einfach. So, ich möchte meinen Taschenrechner auf pimpen, dass er Aufgaben wie z.b 5+5-3 lösen kann. Ich habe aber einfach keine Richtige Idee wie ich dies umsetzen könnte. Ich möchte weder Code Bsp sondern einfach eine kleine Erklärung wie ich dies Umsetzen könnte.
Ich weiß nicht, ob meine Lösung so toll ist, aber ich habs so gemacht
Zahlen und Zeichen werden in separaten Listen gespeichert. Beim Berechnen werden die benötigten Elemente entnommen (und entfernt) und das Ergebnis wird wieder an der Stelle eingefügt, wo vorher die Operanden waren. Die Schleife läuft, bis die Zeichen-liste leer ist.
du brauchst einen Algorithmus der sozusagen die Rechenzeichen als solche Erkennt. Also den String interpretieren und dann die Zahlen und Zeichen umwandeln und ausrechnen lassen. Eventuell gibt es da schon etwas tolles an Java Mathematik Frameworks wie z.B.Math - Commons Math: The Apache Commons Mathematics Library
Mal etwas formaler:
Du möchtest ein Programm schreiben, das einen mathematischen Ausdruck auswertet.
Ein mathematischer Ausdruck ist ein "Wort" einer bestimmten Sprache.
Du solltest dir also zunächst Gedanken darüber machen, wie die formale Sprache "mathematischer Ausdruck" aufgebaut ist (du erstellst also eine formale Grammatik).
Dein erstes Problem ist dann das Wortproblem, für das du zunächst einen Tokenizer und dann einen Parser für die Sprache brauchst.
Anschließend kannst du den vom Parser gelieferten Objektbaum dann semantisch abarbeiten.
Liest sich jetzt sehr formal, die einzelnen Schritte sind aber mitunter recht einfach.
Als Tokenizer kann man z.B. einfach java.util.StringTokenizer verwenden.
So hat dein "Taschenrechner" die Chance, ein richtig gutes und klar strukturiertes Programm zu werden.
Oder du versuchst es "händisch und intuitiv" hinzubekommen, ohne Vorplanung. Dann wird's derselbe Murks wie tausende andere "Taschenrechner-Versuche".
Ich halte einen StringTokenizer für unsinnig, da die Reihenfolge der Delimiter vorgeschrieben ist. Ergo brauchst du für jeden Operanden einen eigenen StringTokenizer. Ergo hast du schonmal für eine simple Interpretation der Zeichen einen aufgeblähten Algorithmus.
Mein Vorschlag hingegen ist, dass du einfach aus dem String ein charArray machst und für jedes Zeichen prüfst ob es eine Zahl oder ein Operand ist. Merke dir den index bis zum nächsten Operanden, falls es einen gibt und nimm die vorigen Zeichen und caste sie in einen double. Du bekommst zwangsläufig Probleme beim interpretieren der Zeichenfolge, wenn z.B. mehrere Operanden aufeinander folgen. Hier könnte man schon bei der Benutzereingabe validieren oder den Algorithmus anpassen damit umzugehen, je nachdem wie es Sinn macht. Letztlich hängt es davon ab, wie komplex der Taschenrechner werden soll.
Eine sehr schöne Möglichkeit ist auch das rechnen mit (umgekehrter) polnischer Notation (die ersten Taschenrechner funktionierten so )
Damit sind verschiedene Klammerungen (Assoziationen) und auch Funktionen leicht umsetzbar mit Hilfe eines Stacks.
Um infix nach postfix zu transformieren gibt es den shunting yard Algorithmus.
Abstract syntax tree ist ein weiteres Stichwort diesbezüglich.
Ich halte einen StringTokenizer für unsinnig, da die Reihenfolge der Delimiter vorgeschrieben ist. Ergo brauchst du für jeden Operanden einen eigenen StringTokenizer. Ergo hast du schonmal für eine simple Interpretation der Zeichen einen aufgeblähten Algorithmus.
Mein Vorschlag hingegen ist, dass du einfach aus dem String ein charArray machst und für jedes Zeichen prüfst ob es eine Zahl oder ein Operand ist. Merke dir den index bis zum nächsten Operanden, falls es einen gibt und nimm die vorigen Zeichen und caste sie in einen double. Du bekommst zwangsläufig Probleme beim interpretieren der Zeichenfolge, wenn z.B. mehrere Operanden aufeinander folgen. Hier könnte man schon bei der Benutzereingabe validieren oder den Algorithmus anpassen damit umzugehen, je nachdem wie es Sinn macht. Letztlich hängt es davon ab, wie komplex der Taschenrechner werden soll.
Quatsch.
a) Der StringTokenizer bekommt mitgegeben, dass er als Delimiter "+-*/()" verwenden soll, und dass ich die Delimiter ebenfalls als Tokens zurückgegeben haben möchte. Warum ich da "für jeden Operanden einen eigenen StringTokenizer" bräuchte, ist mir schleierhaft. Und dass "die Reihenfolge der Delimiter vorgeschrieben" sei - hä? Das ist dem StringTokenizer völlig egal. Und dem logischen Tokenizer auch noch, erst der Parser erkennt nicht-wohlgeformte Ausdrücke.
b) "aus dem String ein charArray machst und für jedes Zeichen prüfst ob es eine Zahl oder ein Operand ist" - genau auf diese Art und Weise wird der Taschenrechner MURKS. Und viel Spaß beim Wandeln von ".78e-3" via "einzelne chars" in eine Gleitkommazahl!
c) Es wird noch schwierig genug, z.B. zu erkennen, ob ein '-' (oder ein '+') als Operator(! nicht "Operand", das sind nämlich die Zahlenwerte...) gemeint ist, oder als Vorzeichen der nachfolgenden Zahl, oder vor einem 'e' das Vorzeichen des Exponent angibt. (Ggf. kann man 'e' als weiteren Delimiter zum StringTokenizer nehmen.)
d) Spätestens wenn auch Klammerung funktionieren soll, oder der Taschenrechner Punkt-vor-Strich beachten soll, ist diese von-links-nach-rechts-Rechnerei am Ende.
Der logische Tokenizer erzeugt eine Liste von Objekten der Klasse "LexicalToken", die z.B. Unterklassen hat "Operator" und "Zahlenwert". Er sollte auch das Problem lösen, dass '+' und '-' evtl. Vorzeichen sind.
Danach kommt der Parser, der aus der Liste eine Baumstruktur aufbaut:
Die Zahlenwerte sind die Blätter, und Operator-Wertigkeit (Punkt-vor-Strich) und Klammerung ordnen, welche Rechnung zuerst (nahe an den Blättern) und welche zuletzt (nah an der Wurzel) ausgeführt werden:
Die Lösung mit dem charArray ist zugegebenrmaßen MURKS . Ein StringTokenizer ist trotzdem kein guter Ansatz, da er die Delimiter in vorgegebener Reihenfolge erwatet. Probiert es doch aus. Ich lasse mich gern eines Besseren belehren. Vielleicht irre ich mich, aber ich habe erst vorgestern an diesem Problem gearbeitet im Sinne einer kleinen Config-Datei für eine kleine App. Wenn z.B. "+-" gesetzt ist, dann wird nach jeden '+' ein '-' erwartet, ansonsten Exception. Aus einem String sollten mehrere Parameter in ein Array geladen werden. Wenn es jedoch nur ein Parameter war, welcher keiner Separierung durch ein als Delimiter angegebenes Komma bedarf, wurde ich unsanft aus dem Programm geworfen, da ein Komma unbedingt an dieser Stelle erfolgen sollte.
Btw... Sehr schöne Ausführung Arilou.
Ich gehe mal in eine andere Richtung. Der "einfache Java-Taschenrechner" besteht für mich aus einem Fenster, in dem 2 Textfelder und 6 Knöpfe sind" +,-,x,/, = , C". Wenn ich das als MVC baue, dann ist doch die Frage, wie ich so Kettenrechnungen hinbekomme. Die Frage in diesem angenommenen Fall ist einerseits, was passieren muss, wenn die actionListener der Button feuern, und wie so der Taschenrechner arbeitet.Andereseits ist auch die Frage, wie die Modellklasse eine Klasse Zahl aussehen sollte, die etwa Methoden Wie Zahl. adddiere(double parameter) zuläßt.
Ich würde vorschlagen dass du mit dem Controller anfängst, denn er wird Dreh- und Angelpunkt. Alles was passiert geht darüber. Schreibe am besten zu Anfang ein paar Tests in denen du verschiedene Strings übergibst, welche per GUI-Eingabe möglich sind. Dann kannst du dich daran machen Klassen und Methoden zu erstellen, welche diese Strings 'richitg' zerlegen. Danach brauchst du quasi nur noch die GUI machen und dafür sorgen dass richtig gerechnet wird.
[...] Ein StringTokenizer ist trotzdem kein guter Ansatz, da er die Delimiter in vorgegebener Reihenfolge erwatet. Probiert es doch aus. Ich lasse mich gern eines Besseren belehren.
danke für den Beweis und das diese falsche Annahme von mir beseitigt ist. Habe nochmal nachgeschaut was eigentlich mein Problem war. Mein Algorithmus hat dierekt nach Tokens mit einer bestimmten Zeichenfolge gesucht. Fälschlicherweise nahm ich an das lag an den Delimiters.