AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Projekte kleiner, vlt auch etwas uneffizienter Mathe Parser

kleiner, vlt auch etwas uneffizienter Mathe Parser

Ein Thema von mr_emre_d · begonnen am 29. Jan 2009 · letzter Beitrag vom 29. Jan 2009
Antwort Antwort
Seite 1 von 2  1 2   
mr_emre_d


Mir war fad

Erkläuterung:
Code:
o Punkt vor Strich wird beachtet
o +-*/ kann er sehr gut lösen
o Klammern () werden unterstützt
evt buggy:
o Potenzieren via ^ möglich
o Wurzel ziehen XsY -> 9s2 --> 3
EDIT
Math Unit wird benötigt

Aufruf könnte wie "ShowMessage( SolveProblem( Edit1.Text ) )" folgen

EDIT #n
Es sind keine Fehlerbehandlungen mit eingebaut worden:
Fehler:
- doppelte Operatoren
- Klammer offen vergessen
- "4+2-" ...
So das ist mein letzter Edit heute ...
Wünsch euch allen eine gute Nacht

Code:
Delphi-Quellcode:
var
  Operators: Set of Char = ['s', '^','+', '-', '*', '/'];
  Clamp: Set of Char = [ '(', ')', #8];
  Numbers: Set of Char = [ '0'..'9' ];

function SolveProblem( Problem: String ): String;
var
  newProblem: String;
  x, t: Word; // x = pos, solution, ...
  Solution: Single;
  function OperatorInString(Buf: String): Boolean;
  begin
    Result := True;
    if Pos('s', Buf) = 0 then
      if Pos('^', Buf) = 0 then
        if Pos('*', Buf) = 0 then
          if Pos('/', Buf) = 0 then
            if Pos('+', Buf) = 0 then
              if Pos('-', Buf) = 0 then
                Result := False;
  end;
  // x3+3 --> x = left | startpos = +
  function GetLeft(P: String; StartPos: Word): Word;
  var
    x: Word;
  begin
    x := StartPos-1;
    while (P[x] in Numbers) and (x>=1) do
      dec(x);
    if x = 0 then
      Result := 1
    else
      Result := x+1;
  end;
  // 3+3x --> x = left | startpos = +
  function GetRight(P: String; StartPos: Word): Word;
  var
    x: Word;
  begin
    x := StartPos+1;
    while (P[x] in Numbers) and (x<=Length(P)) do
      inc(x);
    Result := x;
  end;
  {leftcompo+12}
  function GetLeftComponent(P: String): Single;
  var
    x: Word;
  begin
    x := Pos( 's', LowerCase(P) );
    if x = 0 then
      x := Pos( '^', P );
    if x = 0 then
      x := Pos( '*', P );
    if x = 0 then
      x := Pos( '/', P );
    if x = 0 then
      x := Pos( '+', P );
    if x = 0 then
      x := Pos( '-', P );
    if x = 0 then
      Result := x
    else
      result := StrToFloat( Copy( P, 1, x-1 ) );
  end;
  {123+rightcompo}
  function GetRightComponent(P: String): Single;
  var
    x: Word;
  begin
    x := Pos( 's', LowerCase(P) );
    if x = 0 then
      x := Pos( '^', P );
    if x = 0 then
      x := Pos( '*', P );
    if x = 0 then
      x := Pos( '/', P );
    if x = 0 then
      x := Pos( '+', P );
    if x = 0 then
      x := Pos( '-', P );
    if x = 0 then
      Result := x
    else
      result := StrToFloat( Copy( P, x+1, Length(p) ) );
  end;
  { (1*3*5+3+2 ..) }
  function SolveThatProblems(var P: String ): Single;
  var // 3*5*6+5*6
    Sqrt, Sqr,
    Dot, _Div,
    Plus, Minus,
    x, y: Word;
    c1, c2: Single;
    buf: String;
  begin
    Minus := 0;
    Sqr := Pos( '^', P );
    if Sqr = 0 then
      Sqrt := Pos( 's', LowerCase(P) );
    if Sqrt = 0 then
      Dot := Pos( '*', P );
    if Dot = 0 then
      _Div := Pos( '/', P );
    if _Div = 0 then
      Plus := Pos( '+', P );
    if Plus = 0 then
      Minus := Pos( '-', P );

    if (Sqr > 0) then
    begin
      x := GetLeft(P, Sqr);
      y := GetRight(P, Sqr);
    end else
    if (Sqrt > 0) then
    begin
      x := GetLeft(P, Sqrt);
      y := GetRight(P, Sqrt);
    end else
    if (Dot > 0) then
    begin
      x := GetLeft(P, Dot);
      y := GetRight(P, Dot);
    end else
    if (_Div > 0) then
    begin
      x := GetLeft(P, _Div);
      y := GetRight(P, _Div);
    end else
    if (Plus > 0) then
    begin
      x := GetLeft(P, Plus);
      y := GetRight(P, Plus);
    end else
    if (Minus > 0) then
    begin
      x := GetLeft(P, Minus);
      y := GetRight(P, Minus);
    end else
    begin
      Result := 0;
      Exit;
    end;
    buf := copy( P, x, y-x );
    c1 := GetLeftComponent( buf );
    c2 := GetRightComponent( buf );
    if Sqr > 0 then
      Result := Power( c1, c2 )
    else
    if Sqrt > 0 then
      Result := Power( c1, 1/c2 )
    else
    if Dot > 0 then
      Result := c1*c2
    else
    if _Div > 0 then
      Result := c1/c2
    else
    if Plus > 0 then
      Result := c1+c2
    else
    if Minus > 0 then
      Result := c1-c2;
    delete( P, x, y-x );
    Insert( FloatToStr(Result), P, x );
    if OperatorInString(P) then
      SolveThatProblems(P)
    else
      Result := StrToFloat(P);
  end;
  function KlammerEnde(buf: String): Word;
  var
    kAufs, kZus: Word;
    i: Integer;
  begin
    kAufs := 0;
    kZus := 0;
    for i := 1 to Length(buf) do
    begin
      if buf[i] = '(then
        inc(kAufs)
      else
      if buf[i] = ')then
      begin
        inc(kZus);
        if kAufs-kZus=0 then
        begin
          Result := i;
          Exit;
        end;
      end;
    end;
  end;
begin
  x := Pos('(', Problem);
  if x > 0 then
  begin
    newProblem := Copy( Problem, x+1, KlammerEnde(Problem)-x-1 ); // ausdruck in klammern
    Delete( Problem, x, Length(NewProblem)+2 );
    Insert( SolveProblem( newProblem ), Problem, x);
    x := Pos( '(', Problem );
    if x > 0 then
      Problem := SolveProblem( Problem ); // löse werte in einer klammer auf
  end;
  if OperatorInString( Problem ) then
    SolveThatProblems( Problem );
  Result := Problem;
end;
MfG
 
Dax
 
#2
  Alt 29. Jan 2009, 02:15
Kann dein Parser mit ((1+2)+3)+4 umgehen? Und in der Tat ist das ganze.. naja, sehr langsam. Stringoperationen sind ungefähr das langsamste was es gibt, geschlagen nur von Operationen auf physischem Zeugs
  Mit Zitat antworten Zitat
mr_emre_d
 
#3
  Alt 29. Jan 2009, 02:36
Jetzt schon

Du sagtest stringoperatoren seien zu langsam:
Wie sollte ichs sonst machen ?
  Mit Zitat antworten Zitat
Dax
 
#4
  Alt 29. Jan 2009, 02:39
(1+2)+(3+4)

Du könntest den String zu einem Baum auseinanderpflücken und jeweils einzelne Teilbäume berechnen, wobei Attribute eines Nodes die Operation beschreiben. Damit sparst du dir das löschen/einfügen.
  Mit Zitat antworten Zitat
mr_emre_d
 
#5
  Alt 29. Jan 2009, 02:49
Ok es war ein kleiner Fehler drinnen, der nun gefixt ist
  Mit Zitat antworten Zitat
Dax
 
#6
  Alt 29. Jan 2009, 05:07
Oke, weils so schön ist: 1/*2
  Mit Zitat antworten Zitat
mr_emre_d
 
#7
  Alt 29. Jan 2009, 05:09
ouukaayy... Was ist denn bitte das für eine Rechnung ?
Falls du die Fehlerbehandlung meinst:
Siehe Post ( - sie wird nicht behandelt )

MfG
  Mit Zitat antworten Zitat
Dax
 
#8
  Alt 29. Jan 2009, 05:10
Nagut, wenn du drauf bestehst

2s2 + 1
  Mit Zitat antworten Zitat
mr_emre_d
 
#9
  Alt 29. Jan 2009, 05:11
  Mit Zitat antworten Zitat
Dax
 
#10
  Alt 29. Jan 2009, 05:16
Das ist nicht böse gemeint Ich will dir nur Schwachstellen in deiner Implementation zeigen und dich dazu bringen, selbst danach zu suchen. Der Parser ist an sich schon ein guter Anfang, so ist es ja nicht - aber für Real Word Usage™ noch nicht geeignet.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 +2. Es ist jetzt 17:00 Uhr.
Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf