AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Mathematische Formeln parsen

Ein Thema von Coder1990 · begonnen am 4. Okt 2008 · letzter Beitrag vom 6. Okt 2008
Antwort Antwort
Benutzerbild von Coder1990
Coder1990

Registriert seit: 3. Nov 2007
116 Beiträge
 
Delphi 2005 Personal
 
#1

Mathematische Formeln parsen

  Alt 4. Okt 2008, 13:02
Hallo,

ich habe mir vorgenommen meine Facharbeit im Bereich Mathematik-Informatik zu schreiben und habe mich nun dazu entschieden einen Formel Parser zu erstellen. Nun bräuchte ich vll ein paar Tipps wie ich da am besten vorgehen sollte.

Meine momentane Überlegung sieht folgendermaßen aus:
Jede neu eingespeicherte Funktion wird in einer Klasse TFunction abgespeichert, die über benutzte Variablen bescheid weiß und wie die Funktion als String aussieht. Darüber hinaus besitzt die Klasse TFunction nun einen TBlock der wiederum aus mehreren TBlöcken besteht welche die einzelnen Rechenoperationen in sozusagen in Blöcke fassen.
Bsp: (die {} Klammern symbolisieren Blöcke
2x^2 - x^3 + x(x-2)
-> {{2x^2} - {x^3} + {x(x-2}}
-> {{2}*{{x}*{x}}} - {{x}*{x}*{x}} + {{x}*{{x}-{2}}}

Nun genauer am 1. Rechenblock:
1. Stufe {{2}*{{x}*{x}}}
2. Stufe {2}*{{x}*{x}}
3. Stufe {2} // {{x}*{x}} (das '*' muss sepearat in der 2. Stufe gespeichert werden!)
4. Stufe - // {x} * {x}
5. Stufe - // {x} // {x} ('*' in Stufe 4 abgespeichert)

Wenn ich nun für x einen Wert einsetzen will wird rekursiv sozusagen von unten nach oben alles durchgerechnet.

Leider bin ich in Sachen Rekursion nicht sonderlich begabt und bin mir nicht sicher wie ich das am Besten lösen soll.

Meine momentanen Klassen sehen so aus:

Delphi-Quellcode:
  TBlock = class
  private
  FInnerBlocks:array of PBlock;
  FCalcMethod: array of TCalcMethod;
  FSource: PFunction;
  FNegative: boolean;
  // function Calculate:real;
  public

  // property Result: real read Calculate;
  function AddBlock(s:string):integer;
  procedure AddCalc(a:char);
  property Negative: boolean read FNegative write FNegative;
  property Source : PFunction read FSource write FSource;
  constructor Create;
  function Read(f:string):integer;
  end;


  TFunction = class
  private
  FSourceFunction:string;
  FFunction: PBlock;
  FVars: TStringlist;

  public


  procedure ShowVars(l:TListbox);
  constructor Create(f:string);
  end;
Die rekursive Funktion im TBlock ist "Read" und der Rückgabewert soll das Ende des momentan untersuchen Blocks im String ausgeben, also die Stelle im String wo der von der momentanen Read Funktion untersuche Block aufhört damit die aufrufende Read Funktion weitermachen kann.

Leider komme ich mit "Read" auf keinen grünen Zweig.

MfG
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#2

Re: Mathematische Formeln parsen

  Alt 4. Okt 2008, 13:40
Okay ... also Rekursion ist schon mal einen Schritt zu weit gedahct, würde ich fast sagen ...

Du solltest dir erstmal klar machen, was du genau machen musst. Die Implementation ist erst danach dran.

Im allgemeinen musst du einen Binären Baum aufbauen, der aus sog. Token besteht.

Das ist der kleinste Teil einer mathem. Formel (also so ähnlich, wie dein Block)

Das sieht dann im Endeffekt so aus, dass ein Knoten einen Operanden darstellt, und dieser dann 2 Kinder haben kann. Jedes Kind kann entweder ein weiterer Operand sein, oder ein Symbol (X, Y, 42 oder -1)
(Zumindest bei binären Operatoren wie plus und minus usw.)

D.h. 2x^2 - x^3 + x(x-2)

Wird zu einem Baum:
Code:
*             {-}
      {*}            {+}
  {^}    {2}     {^}        {*}
{X} {2}        {X} {3}   {X}   {-}
                             {X} {2}
Den kannst du dann berechnen (rekursiv oder iterativ) bzw. vorher x einsetzen.

Aber es gibt hier auch schon ein paar Mathe-Parser, da kannst du dir ja mal einen angucken

Edit: Das parsen als Baum hat den Vorteil, dass du nachher schneller Rechnen kannst, als wenn du jedes mal den String parst, wenn du einen neuen X-Wert auswerten willst.
Außerdem kannst du das dann "kompilieren", um es noch schneller zu machen, aber das ist dann schon fortgeschritten
  Mit Zitat antworten Zitat
Benutzerbild von Coder1990
Coder1990

Registriert seit: 3. Nov 2007
116 Beiträge
 
Delphi 2005 Personal
 
#3

Re: Mathematische Formeln parsen

  Alt 6. Okt 2008, 01:06
Danke!

Also nachdem ich mir deine "Lösung" durchgelesen habe, bin ich zu dem Schluss gekommen, dass ich bei meiner Überlegung wohl ein bisschen zu kurz gedacht habe. Meine Methode wäre halb rekursiv halb Schleifenabhängig und damit unglaublich kompliziert geworden.

Ich habe nun in den letzten Tagen versucht diesen binären Baum umzusetzen und es klappt sogar (auch wenn ich noch ein paar kleine Fehler fixen muss wie z.b. dass die "()" - Benutzung zu Problemen führt)!!
Ich nehme aber an, dass ich diese Probleme in den nächsten paar Tagen in den Griff bekomme!

Da mein Projekt auf eine komplette Kurvendiskussion hinauslaufen soll graut es mir schon vor den Nullstellen Berechnungen sowie Nullsetzungen anderer Terme. Nun wollte ich mal im vorab schon fragen wie man das am Besten macht:
Muss man die Gleichung irgendwie 0 setzen und auflösen oder setzt man unendlich viele Werte ein (wohl eher nicht^^) oder gibt es da eine andere schlauerere Methode?

MfG
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#4

Re: Mathematische Formeln parsen

  Alt 6. Okt 2008, 01:13
Zu den Nullstellen: schau dir mal das Newton-Verfahren an

Kurz: Tangente an Punkt a_0 bilden, Nullstele suchen, an f(Nullstelle) Tangente bilden usw. Bis du hinreichend genau dran bist
  Mit Zitat antworten Zitat
Benutzerbild von Hador
Hador

Registriert seit: 11. Dez 2004
Ort: Recke
682 Beiträge
 
Turbo Delphi für Win32
 
#5

Re: Mathematische Formeln parsen

  Alt 6. Okt 2008, 01:56
Hi Coder1990,
am Freitag gab es schon einen Thread zu diesem Thema. Dort habe ich schonmal folgendes zur Vorgangsweise geschrieben:
Zitat von Hador:
- Operatorenreihenfolge feslgegen
- Operator mit der höchsten Priorität in dem String suchen
- Als Wurzel in einen Baum einfügen
- Reststrings (je nach parameteranzahl des Operators/der Funktion) als Child-Knoten eingefügt
- das ganze für die Kinder und alle anderen Operatoren wiederholen
- Nachdem alles aufgeteilt wurde in der untersten Ebene anfangen zu berechnen
Mit einem Binärbaum kommt man leider nicht ganz so weit, da es mathematische Operationen nicht nur mit zwei Variablen gibt.

Übrigends ist Rekursion garnicht so schlacht - wenn auch in Zusammenhang mit einem Baum: Du kannst, nachdem du eine Wurzel gefunden hast, einfach die restlichen Teilstrings wiederum mit der selben Funtion aufrufen und somit weiter zerteilen, bis du den ganzen Ausdruck in deinem Baum untergebracht hast.
Lars Kiesow
http://www.larskiesow.de

Computer gehorchen deinen Befehlen, nicht deinen Absichten.
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#6

Re: Mathematische Formeln parsen

  Alt 6. Okt 2008, 08:07
De Backus-Naur-Form der Grammatik für einen mathematischen Ausdruck enthält eine mögliche Lösung für die Implementierung eines Formelparsers. Schau mal nach 'BNF' oder 'Backus-Naur'. Eine andere Möglichkeit wäre eine Stackmaschine. Du überlegst Dir für jedes Token (Klammer-auf, Klammer-zu, +,-,*,/, Nummern etc.) was mit dem Stack passieren soll.
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:55 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz