2008-09-22 17 views
52

Was ist der intelligenteste Weg, einen Mathe-Parser zu entwerfen? Was ich meine ist eine Funktion, die eine mathematische Zeichenfolge (wie: "2 + 3/2 + (2 * 5)") und den berechneten Wert zurückgibt? Ich habe vor langer Zeit eine in VB6 geschrieben, aber es endete damit, dass es aufgebläht und nicht sehr portabel (oder schlau für die Sache ...) war. Allgemeine Ideen, Pseudo-Code oder echter Code wird geschätzt.Intelligentes Design eines Mathe-Parsers?

+0

können Sie eine Java-Implementierung des Rangierbahnhof Algorithmus hier überprüfen: http://projects.congrace.de/exp4j/ – fasseg

+0

Überprüfen Sie den Code, den ich in https://stackoverflow.com/questions/28256/equation- expression-parser-with-precedence/46722767 # 46722767 – user4617883

+0

Überprüfen Sie den Code, den ich in https://stackoverflow.com/questions/28256/equation-expression-parser-with-precedence/46722767#46722767 – user4617883

Antwort

76

Ein ziemlich guter Ansatz würde zwei Schritte umfassen. Der erste Schritt beinhaltet die Notation converting the expression from infix to postfix (z.B. über Dijkstra's shunting yard). Sobald das erledigt ist, ist es ziemlich trivial, eine postfix evaluator zu schreiben.

+0

geschrieben habe Ich denke nicht Der Rangierbahnhofsalgorithmus kann die korrekte unäre Minusbindung an Basen von Exponenten handhaben. h. es kann -2^3 nicht als - (2^3) sondern nur als (-2)^3 analysiert werden. Ich könnte mich irren, ich weiß es nicht genau. – chbaker0

+0

@ Mebob Das sieht für mich Benutzereingabefehler aus. Ich würde mich nicht darum kümmern, es zu korrigieren. Wenn ich mich gut fühlte, würde ich etwas hinzufügen, um nach dem Produkt zu suchen und den Benutzer darauf aufmerksam zu machen, dass er sich irren könnte. – Yay295

5

Sie haben ein paar Ansätze. Sie könnten dynamischen Code generieren und ausführen, um die Antwort zu erhalten, ohne viel Code schreiben zu müssen. Führen Sie einfach eine Suche nach Laufzeit-generiertem Code in .NET aus, und es gibt viele Beispiele dafür.

Alternativ können Sie einen tatsächlichen Parser erstellen und einen kleinen Syntaxbaum erzeugen, der dann zur Auswertung des Ausdrucks verwendet wird. Auch dies ist für einfache Ausdrücke ziemlich einfach. Schau dir Codeplex an, da ich glaube, dass sie dort einen Mathe-Parser haben. Oder schauen Sie einfach BNF nach, die Beispiele enthält. Jede Webseite, die Compiler-Konzepte einführt, wird dies als ein grundlegendes Beispiel einschließen.

Codeplex Expression Evaluator

1

Angenommen, Ihre Eingabe wird im String-Format ein Infix Ausdruck, können Sie es zu postfix konvertieren und ein Paar von Stapeln mit: ein Operator-Stack und einen Operanden-Stack arbeiten, um die Lösung von dort. Allgemeine Informationen zum Algorithmus finden Sie unter Wikipedia.

4

Wenn Sie eine "immer an" -Anwendung haben, geben Sie einfach die mathematische Zeichenfolge an google und parsen Sie das Ergebnis. Einfacher Weg, aber nicht sicher, ob es das ist, was Sie brauchen - aber schlau in irgendeiner Weise, denke ich.

+2

Nein, nicht wirklich schlau. Aber "erledigt die Dinge". –

+2

Das ist, was ich meine, du bist schlau genug zu wissen, wie man Dinge erledigt ;-) – JRoppert

1

ANTLR ist ein sehr schöner LL (*) Parser Generator. Ich empfehle es sehr.

3

Ich weiß, das ist alt, aber ich stieß auf diesen Versuch, einen Taschenrechner als Teil einer größeren App zu entwickeln und lief über einige Probleme mit der akzeptierten Antwort. Die Links waren IMMER hilfreich beim Verständnis und der Lösung dieses Problems und sollten nicht vernachlässigt werden. Ich schrieb eine Android-App in Java und für jedes Element im Ausdruck "string" speicherte ich tatsächlich einen String in einer ArrayList, während der Benutzer auf dem Tastenfeld tippte. Für die Infix-zu-Postfix-Konvertierung habe ich jeden String in der ArrayList durchlaufen und dann die neu angeordnete Postfix-ArrayList von Strings ausgewertet. Das war fantastisch für eine kleine Anzahl von Operanden/Operatoren, aber längere Berechnungen waren durchweg ausgeschaltet, besonders als die Ausdrücke begannen, auf Nicht-Ganzzahlen auszuwerten. Im vorgeschlagenen Link für Infix to Postfix conversion wird vorgeschlagen, den Stapel zu löschen, wenn das gescannte Objekt ein Operator ist und das topStack-Objekt eine höhere Priorität hat. Ich habe festgestellt, dass dies fast korrekt ist. Wenn ich den topStack-Eintrag aufrufe, wenn der Vorrang höher ist, ODER EQUAL für den gescannten Operator, wurden meine Berechnungen schließlich korrekt ausgeführt. Hoffentlich hilft dies allen, die an diesem Problem arbeiten, und dank Justin Poliey (und fas?) Für die Bereitstellung einiger unschätzbarer Links.

1

Entwickler möchten immer einen sauberen Ansatz haben und versuchen, die Parsing-Logik von Grund auf zu implementieren, normalerweise mit der Dijkstra Shunting-Yard Algorithm endend. Ergebnis ist ordentlich aussehender Code, aber möglicherweise mit Bugs geritten. Ich habe eine solche API entwickelt, JMEP, die all das tut, aber ich brauchte Jahre, um stabilen Code zu haben.

Auch bei all dieser Arbeit können Sie sogar von dieser Projektseite aus sehen, dass ich ernsthaft erwäge, auf JavaCC oder ANTLR umzusteigen, selbst nach all der Arbeit, die bereits erledigt wurde.

Verwandte Themen