Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Software-Projekte der Mitglieder (https://www.delphipraxis.net/26-software-projekte-der-mitglieder/)
-   -   kleiner, vlt auch etwas uneffizienter Mathe Parser (https://www.delphipraxis.net/128395-kleiner-vlt-auch-etwas-uneffizienter-mathe-parser.html)

mr_emre_d 29. Jan 2009 00:54


kleiner, vlt auch etwas uneffizienter Mathe Parser
 
:)

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 29. Jan 2009 01:15

Re: kleiner, vlt auch etwas uneffizienter Mathe Parser
 
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 ;)

mr_emre_d 29. Jan 2009 01:36

Re: kleiner, vlt auch etwas uneffizienter Mathe Parser
 
Jetzt schon :)

Du sagtest stringoperatoren seien zu langsam:
Wie sollte ichs sonst machen ?

Dax 29. Jan 2009 01:39

Re: kleiner, vlt auch etwas uneffizienter Mathe Parser
 
(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.

mr_emre_d 29. Jan 2009 01:49

Re: kleiner, vlt auch etwas uneffizienter Mathe Parser
 
Ok es war ein kleiner Fehler drinnen, der nun gefixt ist

Dax 29. Jan 2009 04:07

Re: kleiner, vlt auch etwas uneffizienter Mathe Parser
 
Oke, weils so schön ist: 1/*2

mr_emre_d 29. Jan 2009 04:09

Re: kleiner, vlt auch etwas uneffizienter Mathe Parser
 
ouukaayy... Was ist denn bitte das für eine Rechnung ?
Falls du die Fehlerbehandlung meinst:
Siehe Post ( - sie wird nicht behandelt )

MfG

Dax 29. Jan 2009 04:10

Re: kleiner, vlt auch etwas uneffizienter Mathe Parser
 
Nagut, wenn du drauf bestehst ;)

2s2 + 1

mr_emre_d 29. Jan 2009 04:11

Re: kleiner, vlt auch etwas uneffizienter Mathe Parser
 
:cry:

Dax 29. Jan 2009 04:16

Re: kleiner, vlt auch etwas uneffizienter Mathe Parser
 
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.


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:29 Uhr.
Seite 1 von 2  1 2      

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