# Formel in einem String während Laufzeit berechnen.



## Murgelmann (9. Nov 2003)

Hi,

ich habe das Problem, daß mein Programm beim starten Formeln als Strings übergeben bekommt.
Nichts kompliziertes, z.B.
"N+1"
im Programm ist nun eine Variable N mit dem Wert 1 definiert.
Wie bringe ich nun das Programm dazu während der Laufzeit den Wert von N
durch obige Formel zu verändern, also rechnet:
N = N + 1

Ich brauche eigentlich keinen Formelinterpreter, mein grundliegendes Problem ist eigentlich
- ich habe 2 Integer  N, X mit beliebigen Werten und einen String Y = "X"
- wie kann ich das Programm dazubringen dem Integer N den Wert von X zuzuweisen nur durch den String Y; das also der Wert von Y "X" zu der Variable X wird

Tausend Dank im Voraus


----------



## schalentier (9. Nov 2003)

Also du hast mehrere Möglichkeiten:


1. eigener Formelinterpreter (is gar nicht so kompliziert)
2. Java Reflection. Probier irgendeineInstanzIrgendeinerKlasse.getClass().getXXX(). Da findest du ne Menge Methoden, um auf Felder/Methoden/etc einer Klasse zuzugreifen. Damit müsste dein Problem lösbar sein
3. DynamicJava ist ein Java Interpreter in Java geschrieben. Damit kannst du Java Code aus Strings heraus ausführen.
Viel spass


----------



## Nobody (9. Nov 2003)

@schalentier kannst du mal kurz anreisen wie der formel interpreter angefangen wird, hab mir sowas auchmal überlegt, jedoch bin ich immer am zerlegen des strings gescheitert (schon in der planungsphase).


----------



## schalentier (9. Nov 2003)

hmm naja also ich kann erklären, wie ich es mal gemacht hab:

1. Es gibt ne klasse StreamTokenizer, der bekommt einen Stream als input und liefert per nextToken()-methode das nächste token. (ein token ist ein atom des streams, also z.b. eine zahl, ein operator (+-*/) eine funktion oder klammern). StreamTokenizer ist nich besonders schön, also empfehle ich dir einen besseren Tokenizer zu schreiben, der das nächste Token ließt und klassifiziert. Außerdem nützlich ist es, wenn man das gerade gelesene Token wieder zurückschreiben kann (push). 

2. Sagt dir EBNF was? Steht für Extended Bakus Naur Form (oder so ähnlich) und damit kann man Sprachen beschreiben. Eine math. Formel ist auch eine Sprache. Das würde dann so oder ähnlich aussehen:

EXPR := (TERM "+"|"-" EXPR) | TERM | "(" EXPR ")"
TERM := (FAKTOR "*"|"/" TERM ) | FAKTOR
FAKTOR := ZAHL | VARIABLE

3. Daraus baust du dir eine Klassenhierarchie auf:

```
abstract class EBNFRule
{
   public abstract void parse( Tokenizer tok );
}
class EXPR extends EBNFRule
{
   public void parse( Tokenizer tok )
  {
     Token t = tok.nextToken();
     if( t==Token.KLAMMER_AUF ) 
     {
       new EXPR().parse( tok );
       t = tok.nextToken();
       if( t!=Token.KLAMMER_ZU ) throw Exception();
     } else
     {
        tok.push(t); // t war keine klammer, also irgendwas anderes für TERM
        do {
           new TERM().parse( tok );
           t = tok.nextToken();
           if( t==Token.PLUS_MINUS )
           {
              new EXPR().parse(tok);
           }
        } while( t==Token.PLUS_MINUS );
        tok.push( t ); // letztes  zeichen zurückschreiben
     }
  }
}
```

natürlich musst du jetzt die instanzen wie EXPR, TERM, FAKTOR, etc irgendwie mitspeichern. da entsteht dann ein baum:

```
(1+2)*3

--*
   |- 3
   |- +
       |- 2
       |- 1
```

ausserdem sollte es neben parse(...) noch evaluate(...) geben, die dann alles zusammenrechnet.

is natürlich nich vollständig, falls du fragen hast, meld dich   

viel spass


----------



## gustav (11. Nov 2003)

Wenn es Dir wirklich nur um den Formelinterpreter geht dann brauchst Du nicht den gesamten Aufwand betreiben und einen eigenen Parser schreiben. Für Java gibt es eine Vielzahl von solchen Parsergeneratoren, z.B. javacc (java compiler compiler)
Diese Dinger generieren Programmcode der genau solche Token liefert wie schalentier beschrieben hat. Mehr sogar noch, es wird gleich auf die richtige Syntax geachtet. Du brauchst eigentlich nichts weiter machen als Dir eine solche Grammatik zu definieren :

```
EXPR := (TERM "+"|"-" EXPR) | TERM | "(" EXPR ")"
TERM := (FAKTOR "*"|"/" TERM ) | FAKTOR
FAKTOR := ZAHL | VARIABLE
```
dann den Parser genieren und mit den gelieferten Token losrechnen.... (theoretisch kannst Du dann auch einen Java Interpreter schreiben)

@Murgelmann
Es kommt immer darauf an, wie komplex Deine Formeln sind. Vielleicht lohnt es sich ja jetzt ein wenig mehr arbeit in diese Sache zu investieren. Dann kannst Du später relativ einfach erweitern.
Auf jeden Fall mußt Du Deinem Programm eine Logik einhauchen, damit es "versteht" was der String bedeutet. Wenn Du jetzt schnell was haben willst, dann hilft Dir vielleicht noch eine Heuristik weiter aber irgendwann ist damit Schluss.


----------

