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