Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Formel Parser (https://www.delphipraxis.net/1528-formel-parser.html)

theomega 5. Dez 2002 20:36


Formel Parser
 
Hallo
ich suche einen Komponenten/eine Function, die mir aus einem String, meinetwegen 'x*2+36*sin(x)' und einem Wert für x die Gleichung ausrechnet. Also bei einem Wert von X=5 also 13,13... Das ganze sollte sehr schnell sein, da die Funktion ein Paar Hunderttausend mal aufgerufen wird.


Mir würde auch eine DLL aus C++ zum Beilspiel reichen. Wenn die denn schneller ist! Auch Assembler-Code ist aktzeptabel, sofern er einfach zu bedienen ist!

Danke

TO

theomega 6. Dez 2002 13:31

Gut, ich habe einmal im Internet gesucht, habe auch nicht viel gefunden. Hier habe ich einen Code, der ziemlich gut funktioniert. Kann den sich mal jemand anschauen und feststellen, ob sich da noch etwas optimieren ließe?

Delphi-Quellcode:
function pos0(const c:char;const s:string):integer;
  var k,z:integer; //z:=Anzahl der Klammern
begin
  z := 0;
  for k:=1 to length(s) do
  begin
    if s[k]='(' then
    begin
      inc(z);
      continue;
    end;
    if s[k]=')' then
    begin
      dec(z);
      continue;
    end;
    if (z=0) and (s[k]=c) then
    begin
      result:=k;
      exit;
    end;
  end;
  Result := 0;
end;


function copyab(const s:string; const i:integer):string;
begin
  Result:=copy(s,i,length(s)-i+1)
end;



function pos0Ex(const c: Char; const s: string; out ResultValue: Integer): Integer;
//pos0Ex findet das Zeichen "+","-" ... nicht innerhalb von Klammern
var k, z: Integer; //z:=Anzahl der Klammern
begin
  z := 0;
  for k := 1 to Length(s) do begin
    case s[k] of
      '(': Inc(z);
      ')': Dec(z);
      else
        if (z = 0) and (s[k] = c) then begin
          Result := k; //Treffer
          ResultValue := k;
          Exit;
        end;
    end;
  end;
  ResultValue := 0;
  Result := 0;
end;


function TermToReal(s:string):real;
//  {Bisher '+' '-' '*' '/' Klammern und 'x' integriert,
//   d.h. gebrochen rationale Funktionen werden ausgewertet
var ps: Integer;
begin
  //showmessage(s); Empfehlenswert zum Verständnis
  if pos0Ex('+',s,ps)>0 then result:=TermToReal(copy(s,1,ps-1))+TermToReal(copyab(s,ps+1)) else
  if pos0Ex('-',s,ps)>0 then result:=TermToReal(copy(s,1,ps-1))-TermToReal(copyab(s,ps+1)) else
  if pos0Ex('*',s,ps)>0 then result:=TermToReal(copy(s,1,ps-1))*TermToReal(copyab(s,ps+1)) else
  if pos0Ex('/',s,ps)>0 then result:=TermToReal(copy(s,1,ps-1))/TermToReal(copyab(s,ps+1)) else
  if pos0Ex('^',s,ps)>0 then result:=Power(TermToReal(copy(s,1,ps-1)),TermToReal(copyab(s,ps+1))) else
  if pos0Ex('$',s,ps)>0 then
  begin
    try
      result:=Power(TermToReal(copy(s,1,ps-1)),1/TermToReal(copyab(s,ps+1)));
    except
      Result := 0;
    end;
  end
  else
  if pos0Ex('s',s,ps)>0 then result:=sin(DegToRad(TermToReal(copyab(s,ps+1)))) else
  if pos0Ex('c',s,ps)>0 then result:=cos(DegToRad(TermToReal(copyab(s,ps+1)))) else
  if pos0Ex('t',s,ps)>0 then result:=tan(DegToRad(TermToReal(copyab(s,ps+1)))) else
  if (s<>'') and (s[1]='(') then begin //Am Anfang und Ende eine Klammer
    s:=copy(s,2,length(s)-2);
    result:=TermToReal(s)
  end else
  if s='x' then result:=x else //oder TermToReal(Form1.Ex.text)
  result:=StrToFloat(s);
end;
[edit=Admin]Delphi-Tags eingefügt. Mfg. Daniel[/edit]

Christian Seehase 6. Dez 2002 16:39

Moin The Omega,

mit anderen Worten, Du bist hier (Threads hier sinnvoll?) nicht weitergekommen? ;-)

theomega 6. Dez 2002 16:43

ja genau! Allerdings ist der Code immer noch relativ (!!!) langsam!


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:56 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