Char Array zu einer Rechnung mit varriblen inklusive Operatoren

Jopt

Grünschnabel
Hallo,
ich bin relativ neu in Java, deswegen stehe ich vor einer Aufgabe, für die ich auch nach längerem Suchen keine Lösung gefunden habe.

Und zwar möchte ich einen Grafischen Taschenrechner programmieren (Erstellung eines Graphen).
Soweit so gut, nur soll der Benutzer die zu zeichnende Funktion per Hand eingeben können. Auch erstmal kein keine Herausforderung.

Problem:
Wie bekomme ich die eingegebene Funktion ausgewertet ?
Beispiel:
userInput : 2x + 5 (leider ein String),
Um den Y Punkt dafür berechnen zu können muss sich das ganze ja irgendwie benutzen lassen...

Jetzt weiß ich nicht wie ich aus diesem String eine Rechenoperation mache (inklusive des Pluses).

Sorry wegen des Fehlenden Programmcodes, aber schien mir nicht notwendig ;D

Danke im Voraus,
Jopt
 

sheel

I love Asm
Hi

das ist ein etwas größeres Thema als ein paar Zeilen Code. Der Java-Compiler kannsfür Java-Code natürlich, aber eine Klasse, die laufende Java-Programme einfach so verwenden können, gibts nicht.


Möglichkeit 1a: Es gibt Libraries, die einem Teile der unten beschriebenen manuellen Schritte abnehmen (zB. http://www.singularsys.com/jep/ oder http://www.formula4j.com/, hab aber keine Ahnung was wie gut ist). Viel vorprogrammiert, aber wie man das aufruft usw. muss man auch erstmal lernen; und die Lib muss immer beim Programm dabei sein.

Möglichkeit 1b: Javascript dafür missbrauchen (um ein häufiges Missverständnis vorzubeugen: Java und javaScript sind trotz des Namens zwei sehr verschiedene Sprachen). Java hat (trotzdem) seit 1.6 eine (teilweise) Verarbeitungsmöglichkeit eingebaut, also für JS-Code während das Javaprogramm läuft.
Nachteile: a) Man hat keine Kontrolle über die Schreibweise der Formeln, zB. muss es Math.sin heißen statt einfach sin usw.; und b) es versteht nun mal nicht nur Formeln, sondern JS-Programme. Wenn der Benutzer was anderes als eine gültige Formel reinschreibt... erstens macnt es was falsches, und zweitens kanns je nach Situation ein Sicherheitsrisiko sein.
Siehe http://stackoverflow.com/questions/4681959/algebra-equation-parser-for-java als Ansatzpunkt.

Möglichkeit 1c: Ähnlich dazu, aber mit Java selber statt JS. Wenn man voraussetzt, dass immer das JDK statt nur JRE installiert ist (also Javacompiler usw. dabei), kann man den Compiler wie alle anderen Programme natürlich auch vom Java-Programm heraus starten. Und es gibt sogar auch eine spezielle JavaCompiler-Klasse. Siehe http://stackoverflow.com/questions/...atically-compile-and-instantiate-a-java-class als Ansatzpunkt.
Nachteile a und b gleich wie bei JS, c) man braucht immer das JDK; d) umständlich

...

Möglichkeit 2: Selbstschreiben.

a) Festlegen was unterstützt werden soll
zB. Operationen: () + - * / sin cos tan pow sqrt
Auch wie große Zahlen es sein dürfen (int double usw. in Java kann ja nur Werte bis zu einem bestimmten Maximalwert speichern. Reicht das, oder will man beliebige Zahlen (BigDecimal-Klassen usw.)?).
Auch ob es immer Diagramme in Form "y = bla x bla" werden oder evt. mehr Variablen erlaubt sind.
usw.

b) Den String zerlegen Teil 1 (könnte theoretisch mit den folgenden Teilen zusammengefasst werden, aber da macht man sich beim Codeschreiben wahnsinnig). zB. mit einer eigenen kleinen Klasse für Typ und Wert, und davon einer ArrayList etc., den String Buchstaben für Buchstabenm durchuntersuchen und die AL füllen, dass man für "-12x + sqrt(x)" dann praktisch die Infos "Minus, Zahl 12, Variable x, Plus, Wurzelfunktion, Klammer auf, Variable x, Klammer zu"hat. Dabei auch Leerzeichen rausfiltern usw.

c) Zerlegen Teil 2: Diese Daten in einem Baum umschichten (Elemente haben also Kindelemente, idealerweise wieder mit einer eigenen Datenklasse), und dabei Sachen beachten wie: 12x ist das Selbe wie 12*x, -12 ist das Selbe wie 0-12 (aber 1-2 ist natürlich nicht 10-2, das - muss vorher nichts oder eine Klammerauf haben), * / kommt vor + -, sin cos tan kommt vor *, Klammern kommen vor allem, a+b+c=(a+b)+c, usw.

Am Ende ideenmäßig für "-12x + sqrt(x/2.5) + 1" sowas wie Folgendes haben:
Code:
Plus
    Operand1: Verschachtelung
        Plus
            Operand1: Verschachtelung
                Multiplikation
                    Operand1: Verschachtelung
                        Minus
                            Operand1: Zahl 0
                            Operand2: Zahl 12
                    Operand2: Variable x
            Operand2: Verschachtelung
                Wurzel
                    Operand1: Verschachtelung
                        Division
                            Operand1: Variable x
                            Operand2: Zahl 2.5
    Operand2: Zahl 1

d) Um das y für ein x auszurechnen, den Baum rekursiv durchgehen und einsetzen/ausrechnen
Also wenn man Plus findet dann die zwei Operanden abfragen (Verschachtelungen per rekursivem Aufruf auflösen, Zahlen einfach so übernehmen, für Variablen die aktuellen Werte einsetzen) und addieren, für Minus eben subtrahieren und so alle Fälle durch, usw.

Natürlich auch beachten, dass es Fehler wie Division durch 0, negative Wurzel usw. geben kann.

e) Für einen Graph eine Menge y ausrechnen, zB. für x in 1-Pixel-Schritten über den ganzen Bereich, und mit den Koordinaten dann zeichnen.

...


Btw. falls man Potenz/Wurzel mit Kommazahlen als Exponent unterstützen will:
Code:
a) x^(-y) == 1/(x^y)
b) x^(1/y) == sqrt[y](x) //also die y-te Wurzel statt die zweite, von x
c) sqrt[1/y] == x^y
d) x^(y/z) == sqrt[z](x^y) == (sqrt[z](x))^y
e) x^1.2 == x^(12/10)
f) x^(12/10) == x^(6/5) //ggT rausdividieren, Euklidischer Algo zum Bestimmen
g) bei Zahlen wie 0.23890312470931 ein paar Kommastellen abscheiden, weil mit 23890312470931 Potenzieren und dann die 100000000000te Wurzel ziehen etwas arg ist
 
Zuletzt bearbeitet:

Jopt

Grünschnabel
Vielen Dank sheel für deine schnelle Hilfe,

ich glaube mein Vorhaben überschreitet wohl fürs erste meine Kapazität. Schöne ausführliche Erklärung auf die ich später auf jeden Fall zurückkommen werde!
Es schien so einfach, ich werde es einfach fürs Erste so machen, dass ich ein paar Funktionen vorschreibe, welche der Benutzer dann auswählen kann.
Ist alles ja lediglich zu Test- und Lernzwecken.

Vielen Dank nochmal sheel!