# Mathefunktion zur Laufzeit einlesen und dann verarbeiten



## Carl (12. Jan 2007)

Hallo!

Mich interessiert ob folgende möglich ist:

Der User soll zur Laufzeit eine beliebige Funktion eingeben, die anschließend z.B. integriert wird. Es soll auf keinen Fall auf einen Funktionenpool o.ä. zugegriffen werden. Ich habe etwas gegoogelt und habe nur einen Hinweis auf BCEL bzw. GNU erhalten, auf deren Seiten wurde ich jedoch nicht schlauer. Was ich bis jetzt weiß:

Der Eingelesene Code muss nachträglich kompiliert werden. Jedoch wie geht so was? Hat da jemand eine gute Infoquelle?


Danke im voraus


Carl


----------



## Wildcard (12. Jan 2007)

Was ist den der 'Funktionspool'?
Ich kann mir aus dieser Beschreibung auch nicht wirklich herleiten was du machen willst.


----------



## Carl (12. Jan 2007)

Also ich möchte folgendes erreichen:

1. Das Programm wird gestartet

2. Der User gibt eine Funktion per Tastatur ein, er soll also nicht aus z.B. 5 Funktionen eine auswählen können mit welcher er Arbeiten will, sondern eine beliebige Funktion eingeben können. 
Um die Sache zu vereinfachen, kann man annehmen, dass die Funktion Java-Syntax konform (also nicht x^3 sondern x*x*x) einzugeben ist.

3. Danach wird mittels Trapezformel das angenäherte Integral berechnet und ausgegeben.

Das ganze muss mit Java geschehen.

Punkt 1 und 3 sind kein Problem. Jedoch bei Punkt 2 habe ich keine Ahnung wie man das anstellt, da man meiner Ansicht nach den eingegebenen Code nachträglich compilieren muss.


Carl


----------



## Marco13 (13. Jan 2007)

Es gibt ... erstmal, theoretisch 2 Möglichkeiten:
1. Du könntest die Funktion (zusammen mit dem ansonsten noch benötzigten Code) in eine .java-Datei schreiben, diese dann (mit dem Java-Internen Java-Compiler) compilieren, die .class-Datei laden, dir mit reflection ein Objekt dieser Klasse erstellen, und auf diesem Objekt dann deine Funktion aufrufen. Funktioniert prima. Hab ich mal gemacht. War aber nur ein Test - es ist nämlich (SEHR zurückhaltend formuliert: ) "unkonventionell". 
Sinnvoller wäre die zweite Möglichkeit:
2. Du könntest in die FAQ schauen. Dort ist beschrieben, wie man einen Mathematischen Ausdruck auswerten kann. Das dort gepostete Programm muss evtl. noch etwas erweitert werden.


----------



## Carl (13. Jan 2007)

Hallo,

also die 2. Möglichkeit kommt wegen der suboptimalen Laufzeit nicht in Frage.
Die erste Möglichkeit ist das was ich suche. Ich hab gerade eben gesehen, dass das mit Java 6 ohne zusätzliche Programme möglich ist. 

Danke für die Hilfe


Carl


----------



## Illuvatar (13. Jan 2007)

Also mit Java 6 (oder auch vorher, da musst du aber extra was runterladen) solltest du eine mitgelieferte Script-Engine verwenden. Denn das, was wirklich am langsamsten ist, ist wohl die erste Möglichkeit, da dabei erst noch kompiliert werden muss.
Wenn du das, was in der FAQ beschrieben ist, selbst programmierst und optimierst, dürfte das wohl das schnellste sein. Allerdings höchstens unmerklich schneller (auch bei vielen Werten) als das mit der ScriptEngine, dafür deutlich aufwändiger.


----------



## Hilefoks (13. Jan 2007)

Warum ein Compiler in diesem Fall schneller sein soll als ein Interpreter verstehe ich nicht. Falls du dich doch noch für einen Interpreter entscheiden solltest schau dir mal diesen an http://www.singsurf.org/djep. 

MfG,
Hilefoks


----------



## SlaterB (13. Jan 2007)

was gibts da nicht zu verstehen? 
ein Interpreter braucht Objekte für die einzelnen Zahlen, Variablen und Rechenoperationen, muss verzweigen,  Bäume entlanglaufen, Operationen aufrufen (Daten in Stack speichern und später wiederherstellen), nach Klammern und sonstigen Regeln schauen..,

dagegen sagt ein compiliertes Programm nur Piep und ist fertig..

alles was das compilierte Programm rechnet muss der Interpreter auch machen,
dazu aber der Riesenoverhead das ganze zu organisieren..


----------



## Marco13 (13. Jan 2007)

@Illuvatar: Das compilieren benötigt EINMAL mehr Zeit - ist dann aber SAU schnell im Vergleich zu einem selbstgestrickten Parser. Spätestens, wenn man die (immer gleiche) Funktion dann ein paar tausend mal mit verschiedenen Werten aufruft, ist das compilierte sicher schneller.


----------



## Wildcard (13. Jan 2007)

Davon abgesehen das Reflection einen ziemlichen overhead erzeugt und alles andere als schnell ist,
ist auch das parsen ein einmaliger Vorgang.
Danach wird genau wie mit der kompilierten Lösung auf Objekten gearbeitet ohne  den Reflection Flaschenhals.


----------



## Illuvatar (13. Jan 2007)

Ergänzung zu Wildcard @SlaterB:

Der Compiler muss genauso die Bäume entlanglaufen, Objekte erstellen, nach Klammern etc. schauen (zudem noch die Klassendefinitionen etc. parsen), usw.

(außerdem wäre noch zu sagen, dass das mit der ScriptEngine aber tatsächlich nichts wäre, da diese wirklich jedesmal neu parsen würde)


----------



## SlaterB (13. Jan 2007)

also ich stelle mir das so vor, dass eine geparste Lösung z.B. für
x*x

ein Mal-Objekt brauch und ein x-Objekt,

um nun die Formel für ein bestimmten Wert zu berechnen,
muss man mühsam das eine (oder mehrere) x-Objekt suchen, darin den Wert setzen,
und dann die Formel durchlaufen lassen,
also ganz generisch erst mal linken Teil + rechten Teil ausrechnen und im Mal-Objekt dann die calculate()-Operation aufrufen
(ich beziehe mich da auf den Parser in der FAQ),
locker 10 Operationsaufrufe wenn nicht viel viel mehr und wer weiß was noch alles zu tun ist

kompiliert ist es dagegen
public double operation1(double x) {
return x*x;
}

das soll NICHT schneller sein? 
wie funktioniert denn ein ebenso schneller Parser?

inwiefern Reflection-Overhead auftritt mag ich nicht beurteilen, das kann gerne sein,
aber wenn's auf die Zeit ankommt muss man dann eben eine ganze Klasse schreiben die ne Minute/ halbe Stunde/ xy Zeit rechnet,
dann fällt der EINE Reflection-Aufruf wohl nicht mehr ins Gewicht 

-------

@Illuvatar:
es geht nicht ums Kompilieren (einmaliger Zeitaufwand), sondern um den Aufwand der Interpretation bei der Anwendung der Formel


----------



## Illuvatar (13. Jan 2007)

Ich bin mittlerweile der Meinung, dass du bei hinreichend vielen Aufrufen wahrscheinlich schon Recht hast. Aber nichtsdestotrotz muss man ja wohl sowohl den Zeitaufwand fürs Kompilieren/Parsen als auch den Zeitaufwand fürs Interpretieren/Ausrechnen miteinberechnen. Und das Interpretieren von der kompilierten Klasse ist zwar sicher schneller, dafür ist aber sicherlich das Parsen schneller als das Kompilieren - und diese Sachen muss man eben abwiegen.


----------



## SlaterB (13. Jan 2007)

da stimme ich gerne zu,
es kommt immer darauf an worauf man sich bezieht


----------

