Dmitri Rettig: Zeichenketten auswerten.

Hallo,

ich bastle gerade an einem Programm für Schaubilder. Der Benutzer gibt eine Zuordnungsvorschrift ein, und das Applet gibt das entsprechende Schaubild aus.
Bislang habe ich zum Zeichnen eines Funktionsgraphen eine vordefinierte Methode benutzt. Um eine neues Schaubild zu erhalten muss man immer wieder neu kompillieren. Bislang habe ich ja an der grafischen Realisierung interessiert.

Jetzt muss ich ein System finden, mit dem es möglich ist, aus einer Zeichenkette eine Zuordnungsvorschrift zu machen. Hier ist ein Beispiel dieser Zeichenkette.

ord = y;
abs = x;
var a = 10;
var b = 2;

f: ord = (2 * a) ^ b;

dieser Code muss in ein TextArea eingetippt werden und bedeutet soviel wie:

Ordinate heisst y;
Abszisse heisst x;
Variable a = 10;
Variable b = 2;

Der Graph der Funktion f wird ermittelt nach der Zuordnungsforschrift y = (2a) hoch b.

Ich muss diese Zeichenkette so umschreiben, dass der Wert später einfach mit String.toDoubleValue(); ermittelt werden kann.

Die Abszisse und die Ordinate kann man leicht abspeichern. Wie ist es aber mit Variablen. Da die Anzahl der Variablen erst zur Laufzeit des Programmes bekannt wird, muss ich für diese ein Array anlegen. Doch ist das nicht so einfach. Wie soll ich diese ansprechen? in dem Teilstring ord = (2 * a) ^ b wird nach Variablen gesucht und diese werden dann durch die Werte ersetzt. Wie geht das? Schliesslich brauche ich noch eine Lösung für das Problem mit ^ ! Ich habe eine Methode geschrieben, mit der es möglich ist, die m Wurzel aus einer Zahl zu ermitteln. Diese Methode wird wie folgt eingesetzt:

Zahl.radix(m);

wie soll ich aber diesen String passend umschreiben?

y = %m (10 - 1)

%m bedeutet die m Wurzel aus dem nächsten Ausruck. Irgendwie fehlt mir der Anfang.

====================================================================

Was ich nun erwarte ist kein Code sondern ein leicht erweiterbares System.

Vielleicht hat jemand schon so eine Bibliothek gemacht.

Ich hoffe, dass ihr mir helfen könnt.

Gruß Dmitri

  1. Hi Dmitri,

    Sowas habe ich mal vor ca. 10 Jahren auf dem C64 in Basic gemacht. Da habe ich aber vorausgesetzt, daß man den Spaß in der Basic-Syntax schreibt und dann wurde der Text einfach als neue Programmzeile in den Quellcode reingehackt. War ein bisschen brutal, aber lief, wenn man sich dran hielt.

    Heute in Java? Da wirst Du wohl um einen Funktionsinterpreter nicht umhin kommen, also "+" entspricht einer Addition usw. und das inclusive Vorrangregeln und Klammern.

    Aber für die Wurzel gibt es doch in der Math-Bibliothek normalerweise die function sqrt (square root). Und für allgemeine Potenzen gibt es die function pow - auch in der Math-Bibliothek. Und dann heißt es eben in Deinem Funktionsinterpreter: Wenn "^", dann pow(Ausdruck davor, Ausdruck dahinter).

    Ich hoffe, daß Dir das ein ganz klein wenig nützt.

    Gruß und gute Nacht
    Andreas

  2. Hi,

    Ich muss diese Zeichenkette so umschreiben, dass der Wert später einfach mit String.toDoubleValue(); ermittelt werden kann.

    _Musst_ Du? Du willst die Rechenvorschrift interpretieren und das Ergebnis ermitteln, oder?
    In welcher API-Version hat String eine Methode "toDoubleValue();"?

    Die Abszisse und die Ordinate kann man leicht abspeichern. Wie ist es aber mit Variablen. Da die Anzahl der Variablen erst zur Laufzeit des Programmes bekannt wird, muss ich für diese ein Array anlegen.

    Dafür gibt es Collections wie z.B. einen Vector.

    Doch ist das nicht so einfach. Wie soll ich diese ansprechen? in dem Teilstring ord = (2 * a) ^ b wird nach Variablen gesucht und diese werden dann durch die Werte ersetzt. Wie geht das?

    Du könntest z.B. definieren: Alle "Variablen" eines Ausdrucks/einer Anweisung werden durch einen "Char" (besser: String der Länge 1) repräsentiert und benutzen die "reservierten" Zeichen [a|b|c].

    Viel Grüße,
    Martin

    1. Hi,

      Ich muss diese Zeichenkette so umschreiben, dass der Wert später einfach mit String.toDoubleValue(); ermittelt werden kann.
      _Musst_ Du? Du willst die Rechenvorschrift interpretieren und das Ergebnis ermitteln, oder?
      In welcher API-Version hat String eine Methode "toDoubleValue();"?

      Ich benutze noch das JDK 1.2 API und kompilliere mit JDK 1.3 [ich warte noch, bis ich DSL kriege]

      Die Abszisse und die Ordinate kann man leicht abspeichern. Wie ist es aber mit Variablen. Da die Anzahl der Variablen erst zur Laufzeit des Programmes bekannt wird, muss ich für diese ein Array anlegen.
      Dafür gibt es Collections wie z.B. einen Vector.

      Aha, ich habe mal vom Vector was glesen, konnte aber nicht verstehen, was das sein soll [bin kein Eglisch As]. Muss noch mal versuchen.

      Doch ist das nicht so einfach. Wie soll ich diese ansprechen? in dem Teilstring ord = (2 * a) ^ b wird nach Variablen gesucht und diese werden dann durch die Werte ersetzt. Wie geht das?
      Du könntest z.B. definieren: Alle "Variablen" eines Ausdrucks/einer Anweisung werden durch einen "Char" (besser: String der Länge 1) repräsentiert und benutzen die "reservierten" Zeichen [a|b|c].

      Darüber habe ich auch nachgedacht, aber der Benutzer soll auch Variablen wie "Autos", "Räder" usw. eingeben können.

      Gruß Dmitri

      1. Hi!

        Die Abszisse und die Ordinate kann man leicht abspeichern. Wie ist es aber mit Variablen. Da die Anzahl der Variablen erst zur Laufzeit des Programmes bekannt wird, muss ich für diese ein Array anlegen.
        Dafür gibt es Collections wie z.B. einen Vector.

        Aha, ich habe mal vom Vector was glesen, konnte aber nicht verstehen, was das sein soll [bin kein Eglisch As]. Muss noch mal versuchen.

        Hm, für solche Variablensammlungen wäre vielleicht eine HashMap angebrachter:

        HashMap variablen = new HashMap();
        //Name/Wert-Zuordnung:
        variablen.put("pi", new Double(3,141));
        //Variable abfragen:
        double x = ((Double)variablen.get("pi")).doubleValue();

        Du kannst natürlich die Werte auch als String speichern (String s=(String)variablen.get("pi");) - als Wert-Parameter (und auch als Schlüssel) nimmt die HashMap jedes beliebige Object an.

        VG Simon

  3. Hi,

    jetzt habe ich schon mal ein Konzept entwickelt. Znächst einmal soll das Programm im analytischen Bereich Anwendung finden, und da wird nun mal der Funktionswert f(x) von x, x zugeordnet. Aus diesem Grunde reicht ja schonmal ein TextField.

    f(x) = [hier Zuordnungsvorschrift eingeben     ][zeichne]

    Spart viel Arbeit.

    Nun habe ich einen String:

    2 * (x + 4)

    Dieser String wird ohre Lehrzeichen geschrieben, dann sieht er wie folgt aus:

    2*(x+4)

    Jetzt nach Operatoren (?) suchen:

    *+-/

    gefunden, der erste ist *

    linken Ausdruck suchen: 2, rechten Ausdruck suchen: ( - wenn Klammer steht, dann die schlussklammer suchen ... gefunden.

    der Ausdruck ist x+4

    das das ganze in einer for Schleife abläuft kann man diesen Ausdruck berechnen.

    Durch Abrage nach dem Operator *+-/ ist auch die Operatioin möglich.

    if (Operator == "*")
        return Ausruck1 * Ausdruck2
    else if (...)
    ...

    Allerdings hat das System auch einige Nachteile:

    1. Ich weiss nicht, wie ich diese Daten verwalten [sortieren und darauf zugreifen] soll.
    2. Dieses System ist sehr schwer erweiterbar [und das entspricht JAVA ansich]

    Ich war schon auf WWW-Seiten sämtlicher Taschenrechnerhersteller, aber die sagen nicht, wie diese Funktionieren ;-( [KAPITALISTEN!]

    Trauriger Gruß von mir...

    1. Hi!

      2 * (x + 4)

      Hui, Du willst also einen Parser für mathematische Terme schreiben - da hast Du aber was vor Dir. Hab ich auch schon mal versucht. Erleichter Dir die Arbeit und guck mal, ob Du sowas nicht irgendwo schon fertig findest.

      das das ganze in einer for Schleife abläuft kann man diesen Ausdruck berechnen.

      Also, das iterativ anzugehen ist zwar möglich (so arbeiten auch die meisten Parser - Operatoren und Zahlen werden dann auf Stacks geschoben), ich habe das damals aber mit einer rekursiven Funktion gelöst. Das macht auch das Verarbeiten von Klammerausdrücken (also auch Funktionen) und Rangfolgen bei den Operatoren (z.B. Punkt-Vor-Strich) leichter.

      Ich war schon auf WWW-Seiten sämtlicher Taschenrechnerhersteller, aber die sagen nicht, wie diese Funktionieren ;-( [KAPITALISTEN!]

      Das würde Dir eh nicht helfen.

      VG Simon