[Codeschnipsel] MatheParser

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • [Codeschnipsel] MatheParser

    Soso. Nen Schnipsel ist es nicht, ist bissle länger, aber was solls.
    Ich stell hier mal meinen Mathe-Parser rein.
    Der funktioniert ganz super, hat bei mir immer die richtigen ergebnisse ausgerechnet, kann um mehr funktionen erweitert werden und es können zur laufzeit neue macros hinzugefügt werden (ein wird ähnlich einer funktion aufgerufen, aber ist eig. nur eine abkürzung.).
    Der code ist bissle kagge, denn ich hätte nen par sachen lieber mit c-strings machen sollen.

    Nuja, der ein oder andere kanns vieleicht gebrauchen. viel spass damit :)
    freue mich auf kritik oder sowas, bzw wünsche mir das jemand was dazu sagt ;D ^^
    Mit dem Code könnt ihr machen was ihr wollt. Ich übernehme keine Garantie fürs richtigrechnen (sollte aber eig. )

    Download

    Erklärung:

    Der "MathParser" hat 2 "große" klassen.
    Die eine, der CParserConverter (blöder name) Parst einen Mathe-String und wandelt ihn in ein Array (Postfix) um.
    Danach kann das array mit dem CParserEvaluater (noch ein doofer name) ausgerechnet werden.
    Dem Evaluator kann vor dem rechnen noch Funktionen, Variablen und Macros hinzugefügt werden.

    Was kann das ding:

    operatoren: + - * / ! % = < > <= >= == != ( ) && ||
    funktionen: max 9 argumente, geben immer double zurück
    macros: max soviele argumente wie ein int fassen kann, geben immer double zurück, können während des laufens erstellt und an den evaluator "angehangen" werden.

    Macros:

    Macros sind eigentlich nur eine Weitere Rechnung. Die Argumente die einem Macro übergeben werden können in dem Macro mit ARG_n (n steht für den index des arguments) abgerufen werden.
    Ein Macro zur umrechnung von deg -> rad sähe so aus:

    Quellcode

    1. CParserMacro * myMacro = [CParserMacro macroWithExpression:@"ARG_1 * (PI/180)"];
    2. [myMacro setMinArguments:1];
    3. [myMacro updatePostfixExpression]; //wandelt das macro in ein postfix-array um.
    4. [evaluator setMacro:myMacro forKey:@"degToRad"];

    (PI muss vorher als variable dem evaluator hinzugefügt werden)
    Um ein Macro in der Rechnung zu benutzen muss der MacroIdentifier vor dem macro stehen. standartmäßig ist das das '#' zeichen, kann aber nach bedarf verstellt werden

    Und noch was: Der Converter überprüft nicht ob variablen, funktionen und macros überhaupt existieren (wie soll er auch). Der Evaluator tut die dummerweise (noch) nicht. das heist man kann irgendwelche funktionen benutzen, und sich dann übers ergebnis wundern.^^

    Wichtig:

    Wenn mehrere Zuweisungen hintereinander stehen müssen diese durch ';' getrennt werden, sonst schmeist der evaluator ne exception.
    das ';' kann alles möglich trennen, somit kann man zuweisung und eine rechung in eine "durchlauf" machen bsp.: "A=1;B=3;A+B" würde 4 ergeben.
    Ich rate allerdings davon ab, das zu benutzen, da es noch ein bisschen fehlerhaft ist. besser ist es das ganze so zu machen: "(A=1)(B=3)A+B"

    Macros sind eigentlich was furchtbar überflüssiges. :D
    Och bin mir nicht sicher, aber ich glaube ich habe nen speicherleck drinnen, wenn ja dann ist der ber extrem leicht zu beheben.

    Dieser Beitrag wurde bereits 14 mal editiert, zuletzt von Johannes Wolf () aus folgendem Grund: Hab da mal was hinzujefücht

  • Scheint zu funktionieren, ist sicher auch praktisch, aber der Code ist nicht so das wahre. Damit das wirklich verwendbar wird muss noch einiges getan werden. Der Code ließe sich sicherlich deutlich vereinfachen, wenn man einige vorhandene Sprachmittel auch nutzen würde (z.B. switch/case, enums, @property/@synthesize, union, ...). Ansonsten ist aber wohl das größte Manko der Unterschied zwischen den Makros und Funktionen, die sollten auf jeden Fall vereinheitlicht werden.

    Wenn du nichts dagegen hast lade ich das ganze mal nach github hoch, damit man da vernünftig mit mehreren dran arbeiten kann.
  • kannst hochladen, git aber schon eine stark veränderte version... werde die diese woche hochladen, zudem soll das ganze überarbeitet werden, so wie du gesagt hast, grade die CParserEvaluator klasse ist bissle misst.
    Vieleicht sollte an manchen stellen auch lieber mit CStrings gearbeitet werden, denn sonst geht switch/case ja schlecht.... richtig. enums müssen rein ;D
    Will die Klassen Converter & Evaluator nochmal omplett neu schreiben, der rest ist finde ich meist ganz ok.

    propertys mag ich nicht, drumm benutze ich sie nicht ;)
    Ich würds ganz gerne selber auf git/sourceforge hochldaen, k?

    Danke

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Johannes Wolf ()

  • @Zerm: Das funktioniert gut mit LLVM, so etwas habe ich auch schon mal gemacht. Lohnt sich aber nur, wenn du eine Funktion sehr oft berechnen willst, z.B. für numerische Integration oder so etwas. Wenn du einen Ausdruck nur ein mal berechnen willst ist so ein Ansatz wie dieser hier schneller. Wenn ich den Benutzer statt Zahlen auch einfache Ausdrücke eingeben lassen möchte macht es sicher keinen Sinn dafür LLVM mit einzubinden.
  • dergraf schrieb:

    @Zerm: Das funktioniert gut mit LLVM, so etwas habe ich auch schon mal gemacht. Lohnt sich aber nur, wenn du eine Funktion sehr oft berechnen willst, z.B. für numerische Integration oder so etwas. Wenn du einen Ausdruck nur ein mal berechnen willst ist so ein Ansatz wie dieser hier schneller. Wenn ich den Benutzer statt Zahlen auch einfache Ausdrücke eingeben lassen möchte macht es sicher keinen Sinn dafür LLVM mit einzubinden.

    Jo, ich hatte nicht-lineare Optimierung mit beliebiger Zielfunktion im Auge, daher sollte das schon etwas flotter laufen ;)
    C++