math. Formeln ausrechnen in Java...

Hallo,

ich hab da mal nen Problemchen.
Ich sitze an einem Programm, was den Graphen einer math. Funktion. graphisch darstellen soll. Bisher habe ich die Funktion (z.B. x+4) als char aufgenommen. Die Funktion soll dann durch eine Schleife gejagt werden, welche dann den Graphen ausgibt. Wenn ich nun y = char programmiere, kommt (verständlicher weise) auch nur ein char dabei raus. gibts ne Möglichkeit, dass der Schleifencode sich quasi während der Laufzeit ändert (z.B. bei neueingabe einer neuen Funktion).
Vorweg schon mal vielen Dank für die Antworten

Grüße

Happy
 
Du wirst den übergebenen String zerstückeln müssen, soll bedeuten: Nach allen x suchen, mögliche Konstanten beachten und natürlich Klammern und sonstige Vorrangregeln nicht vergessen. Ich denke das ganze ist jedoch ziemlich aufwendig und könnte einiges an Zeit beanspruchen. Ich selber habe mir darüber auch bereits Gedanken gemacht, bin aber bei der zündenden Idee zur Abspeicherung der Formel hängen geblieben. Es wäre schließlich sehr umständlich, diese Stringbehandlung jedesmal aufs neue durchzuführen.

Kurzum, viel Arbeit und viel Können von Nöten.
 
Das Problem ich auch, als ich mit 'nem Kumpel im Rahmen eines Delphiprojekts eine Funktionuntersuchung geschrieben hab.
Als Speicher hab ich für die Anstiege ein Array genommen.
Hab mal den entsprechenden Teil angehängt.

Ist zwar Delphi, aber für die Idee sollte es reichen.
Code:
unit Lesen;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    Button1: TButton;
    Label1: TLabel;
    Edit2: TEdit;
    Edit3: TEdit;
    Edit4: TEdit;
    procedure Button1Click(Sender: TObject);
   private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var mx, expo, abl :array of real;                                                                   //   dynamische arrays als speicher für anstiege und exponenten
var y  :String;                                                                                     //   eingabe text
var h, o, i, j, k, e, d, a, p, g, r :integer;                                                       //   zählvariablen
var b : real;                                                                                       //   werte für die arrays
begin

y:=Edit1.text;                                                                                      //   )
o:=0;                                                                                               //   )
i:=1;                                                                                               //   )
j:=0;                                                                                               //   )
h:=1;                                                                                               //   )-- einrichten der zählvariablen
b:=0;                                                                                               //   )
d:=1;                                                                                               //   )
e:=1;                                                                                               //   )
p:=-1;                                                                                              //   )
r:=0;                                                                                               //   )

for h:=1 to length(y) do                                                                            //   )
    case y[h] of 'x' : o:=o+1;                                                                      //   )-- auszählen der benötigten arraylänge
    end;                                                                                            //   )

if o>0 then setlength(mx,o);                                                                        //   )
if o>0 then setlength(expo,o);                                                                      //   )-- festlegen der arraylänge

for i:=0 to o-1 do                                                                                  //   )
    mx[i]:=1;                                                                                       //   )
for i:=0 to o-1 do                                                                                  //   )-- zuweisen von 1 an jede array stelle
    expo[i]:=1;                                                                                     //   )

h:=1;                                                                                               //   zurücksetzen

for h:=1 to length(y) do                                                                            //   schleife für die anstiege
    if y[h] = 'x' then                                                                              //   auslesen von [y]
                       if h>1 then                                                                  //
                       begin                                                                        //
                                      g:=1;                                                         //      multiplikator, wenn anstieg negativ -> g=-1
                                      d:=1;                                                         //      multiplikator, umschreiben des anstiegs in array
                                      b:=0;                                                         //      endwert für array
                                      k:=0;                                                         //      abbruch bedingung in repeat schleife
                                      p:=p+1;                                                       //      stelle im array
                                      j:=-1;                                                        //      anzahl der stellen des anstiegs
                                      a:=h-1;                                                       //      stelle in [y] vor 'x'

                                      repeat j:=j+1;                                                //   repeat schleife zur bestimmung der stellen des anstiegs

                                             case y[a-j] of                                         //   )
                                                '1','2','3','4','5','6','7','8','9','0': k:=0       //   )-- überprüfen ob die stelle [a-j] in [y] eine zahl ist
                                                else k:=1;                                          //   )
                                             end;                                                   //
                                             if a-j=0 then                                          //   )
                                                k:=1;                                               //   )-- überprüfen ob anfang von Edit1 erreicht wird
                                                                                                    //
                                      until  k=1;                                                   //   abbruchbedingung
                                                                                                    //
                                      if y[h-j-1] = '-' then                                        //   )
                                         begin                                                      //   )
                                                             g:=-1;                                 //   )-- ändern des multiplikators [g] wenn anstieg negativ
                                         end;                                                       //   )

                                    repeat b := b + StrToFloat(y[h-e]) * d;                         //   )
                                           d:= d * 10;                                              //   )
                                           e:= e + 1;                                               //   )-- umschreiben des anstiegs in den wert [b]
                                    until  e-1 = j;                                                 //   )

                                    e:=1;                                                           //   zurücksetzen von [e]

                                    mx[p]:=b*g;                                                     //   zuweisen des wertes [b]*[g] an das array [mx] an der stelle [p]

                                    edit2.text:=FloatToStr(mx[p]);                                  //   anzeige des letzten wertes in [mx] ## überprüfung ##

                       end;                                                                         //

p:=-1;                                                                                              //   zurücksetzen von [p]

for h:=1 to length(y) do                                                                            //   schleife für die exponenten
    if y[h] = '^' then                                                                              //   auslesen von [y]
                      if h>1 then                                                                   //
                         begin                                                                      //
                                      r:=0;                                                         //   bedingung für ein '-'
                                      g:=1;                                                         //   multiplikator, wenn anstieg negativ -> g=-1
                                      e:=-1;                                                        //   stelle nach '^'
                                      d:=1;                                                         //   multiplikator, umschreiben des anstiegs in array
                                      b:=0;                                                         //   endwert für array
                                      k:=0;                                                         //   abbruch bedingung in repeat schleife
                                      j:=-1;                                                        //   anzahl der stellen des anstiegs
                                      p:=p+1;                                                       //   stelle im array

                                      repeat j:=j+1;                                                //   repeat schleife zur bestimmung der stellen des exponenten

                                             case y[h+1+j] of                                       //   )
                                                '1','2','3','4','5','6','7','8','9','0': k:=0       //   )-- überprüfen ob die stelle [h+1+j] in [y] eine zahl ist
                                                else k:=1;                                          //   )
                                             end;                                                   //
                                                                                                    //
                                             if y[h+1] = '-' then                                   //   )
                                                begin                                               //   )
                                                                    if r=0 then                     //   )
                                                                    begin                           //   )-- schleife für die akzeptanz eines '-'
                                                                               r:=1;                //   )
                                                                               k:=0;                //   )
                                                                    end;                            //   )
                                                end;                                                //   )
                                                                                                    //
                                             if h+j=length(y) then                                  //   )
                                                k:=1;                                               //   )-- überprüfen ob ende von Edit1 erreicht wird
                                                                                                    //
                                      until  k=1;                                                   //   abbruchbedingung

                                    a:=h+j;                                                         //   festlegen der letzten stelle des exponenten

                                    if y[h+1] = '-' then                                            //   )
                                       begin                                                        //   )
                                                         g:=-1;                                     //   )-- ändern des multiplikators [g] wenn anstieg negativ
                                                         j:=j-1;                                    //   )   ändern des [j] da sonst "StrToFloat('-')" -> fehler
                                                                                                    //   )
                                       end;                                                         //   )

                                    repeat e:= e + 1;                                               //   )
                                           b := b + StrToFloat(y[a-e]) * d;                         //   )
                                           d:= d * 10;                                              //   )
                                                                                                    //   )-- umschreiben des exponenten in den wert [b]
                                    until  e+1 = j;                                                 //   )

                                    expo[p]:=b*g;                                                   //   zuweisen des wertes [b]*[g] an das array [expo] an der stelle [p]

                                    edit3.text:=FloatToStr(expo[p]);                                //   anzeige des letzten wertes in [expo] ## überprüfung ##

                         end;                                                                       //



e:=-1;                                                                                              //   zurücksetzen von [e]

if o>0 then setlength(abl,o);                                                                       //   festlegen der arraylänge

for i:=0 to o-1 do                                                                                  //   )
begin                                                                                               //   )
    e:=e+1;                                                                                         //   )-- ausgeben des produkts der letzen werte aus [mx] und [expo]
    edit4.text:=FloatToStr((mx[e])*(expo[e]));                                                      //   )
end;                                                                                                //   )




end;

end.
 
Die Problembeschreibung ist etwas doppeldeutig: möchtest Du nun eine Funktion (fest im Programm verankert) nur richtig darstellen oder auch noch vom User dynamisch eingeben können? Im zweiten Fall müsste man einen Parser schreiben, was nicht ganz so einfach ist (kommt auf Deine Vorkenntnisse an ;) )
 
Also zur Speicherung nach dem parsen hätte ich ne Idee. Es handelt sich doch im Grund um eine Baumstruktur. Jeder Knoten besteht aus 2 Ausdrücken und einem Operator. Bzw man kann es ja auch so sehen, dass jeder Operator ein Knoten ist und 2 Ausdrücke bzw wieder Operatoren als Children hat.

Dazu baut man sich jetzt ne schöne Klassenstruktur. Möglichst so, dass man im Root-Operator nur noch execute() oder sowas ausführen muss und der Rückgabewert das Ergebnis ist.

Fehlt nur noch die Möglichkeit Variablen mit einzubeziehen - aber das kriegst du sicher auch noch hin.
 
Hallo Alle zusammen,

erst mal vielen Dank an alle die sich Mühe und Gedanken um mein Problem gemacht haben.
Ich habe das Problem etwas mehrdeutig angegeben. Ich habe eine GUI, in der der User eine "belibige" math. Funktion eingibt, welche dann berechnet, analysiert und (graphisch) ausgegeben wird. Die Berechnung ist momentan mein Problem, da mein Programm irgendwo eine Schleife hat, in der x die Formel durchläuft. Das Problem besteht darin, den Eingabestring von z.B. "x^2+x-4" auf die Programmzeile y = (i*i)+i-4; umzuformen. Der String wird vom Benutzer während der Laufzeit eingegeben und geändert. Der Vorschlag von benediktibk bzw CDW bezüglich eines Parsers bringt schon mal eine Richtung ins Dunkel. Ich denke ich werde auch (deine Erlaubnis vorausgesetzt, Banur) einige Zeilen deines codes übernehmen.
Das Problem des speicherns als Array, Baum, etc. ergibt sich nicht, da es mehr Recourcen verschlingt auf einem Array nach einer bestimmten Position zu suchen, als den Funktionswert einfach neu z berechnen. Der Graph selbst besteht dann also aus einer Menge von JLine-Objekten, wozu kein weiteres Array nötig ist (sein sollte!).

Grüße

Happy
 
also unter Linux gibt es schon genau das, was du da machen willst (allerdings wohl ehr in C++ geschrieben)
nennt sich glaub ich "kplot" und müsste in irgend nem KDE-Paket mit drin sein...

vieleicht lässt sich da ja auch was abgucken ;-)
 
Original von Happydead
Ich denke ich werde auch (deine Erlaubnis vorausgesetzt, Banur) einige Zeilen deines codes übernehmen.
Klar kannst du den verwenden.
Wir hatten das auf die Weise gelöst, weil wir ua. auch die Ableitungen etc. berechnet haben.
Hab das fertige Programm mal angeängt, wenn du noch was brauchst kann ich auch den sourcecode noch raus suchen.
 
Zurück
Oben