Page 1 of 4 1 2 3 ... LastLast
Results 1 to 15 of 46

Thread: NLDRcsEval

  1. #1

    NLDRcsEval

    Hoi,
    Er is weer een nieuwe unit in NLDDanyUtils: NLDRcsEval. Deze unit beval 1 class: TSimpleEval

    ------------
    De sources van NLDDanyUtils zijn te vinden in:
    ftp://ftp.nldelphi.com/public/OpenSo.../NLDDanyUtils/
    ------------

    Dit is de interface:
    Code:
    interface
    
    uses Classes, SysUtils;
    
    const
      SimpleEvalOperators = ['+', '-', '*', '/', '^', '%', '=', '>', '<', '|', '&'];
    
      SimpleEvalFunctions: array[0..28] of string =
      ('abs', 'int', 'frac', 'round', 'ceil', 'floor', 'sum', 'avg',
        'min', 'max', 'sqrt', 'pi', 'logn', 'log', 'power', 'sign',
        'ifthen', 'not', 'rad', 'deg', 'cmp', 'ln', 'exp',
        'sin', 'cos', 'tan', 'arcsin', 'arccos', 'arctan');
    
    type
      TSimpleEval = class
      private
        FFormula: string;
        FVars: TStringList;
        FNoFunctions: boolean;
        function GetResult: real;
        function EvalNumerical(S: string): real;
        function HasParenthesis(S: string; var LeftParenthesis, RightParenthesis: Integer; var Arg_: string; StartPos: Integer = 1): boolean;
        function HasFunction(S: string; var Func_, Arg_: string; var B, E: Integer): boolean;
        procedure ReplaceFunctionCalls(var S: string);
        procedure ProcessBetweenParenthesis(var S: string);
        function SolveFunction(Func_, Args_: string): real;
        procedure RemoveOuterParenthesis(var S: string);
        function GetValue(S: string): real;
        function IsNumber(S: string): boolean;
      public
        property Formula: string read FFormula write FFormula;
        procedure SetVar(Name: string; Value: real); overload;
        procedure SetVar(Name: string; Value: string); overload;
        procedure ClearVars;
        property Result: real read GetResult;
        property NoFunctions: boolean read FNoFunctions write FNoFunctions;
        constructor Create;
        destructor Destroy; override;
      end;
    
    type ESimpleEvalException = class(Exception);
    De class implementeert een (vrij) simpele (algebraische of infix notation) expressie evaluator die een beperkt aantal operatoren aankan. (let op: de "%" berekent het "percentage", dus "Left % Right" geeft "Left / Right * 100").
    De evaluatie gebeurt altijd van links naar rechts (dus "*" weegt niet zwaarder dan bv "-"), maar en zijn wel haakjes toegelaten, waarvan de inhoud dus eerst ge-evalueerd wordt (weer van links naar rechts, tenzij... enz...). Dus:
    2 + 3 / 5 ^ 4 -15 * 2 is eigenlijk (((((2 + 3) / 5) ^ 4) -15) * 2).

    Er kan gewerkt worden met "variabelen" (die dus eerst moeten "gedeclareerd" worden met "SetVar") of met numerieke constanten (vb "1.2"). Even onderstaand voorbeeld uitproberen en je ziet het wel.

    Er zijn nu ook een aantal wiskundige en goniometrische functies beschikbaar, zie de interface. Alle functie aanroepen moeten haakjes hebben, ook als er geen argumenten zijn, vb "Pi()".

    Wel opletten voor de "." of "," in variabelen of constanten: de decimal separator volgt die van je windows. Als je functies gebruikt dan moet je wel als "decimalseparator" de "." gebruiken: de komma dient als scheidingsteken tussen argumenten.

    Als je geen functies gebruikt in je toepassing van TSimpleEval, schakel die dan uit door property "NoFunctions" op "true" te zetten, dat maakt de evaluatie heel wat sneller.

    Een voorbeeld van gebruik:
    Code:
    uses RcsEval;
    
    procedure TForm1.Button1Click(Sender: TObject);
    var E: TSimpleEval;
    begin
      E := TSimpleEval.Create;
      try
        E.Formula := Edit1.Text;
    
        E.SetVar('a', Edit2.Text);
        E.SetVar('b', Edit3.Text);
        E.SetVar('c', Edit4.Text);
        E.SetVar('d', Edit5.Text);
    
        Label1.Caption := FloatToStr(E.Result);
      finally
        E.Free;
      end;
    end;
    Bijgevoegd:
    - een simpel "TestEval" project, laat toe even te experimenteren...
    - het grafische testprogramma van SVG dat hier gebruik maakt van TSimpleEval
    Attached Files Attached Files
    Last edited by Dany; 20-Jul-07 at 21:15.

  2. #2
    Nu nog een try-finally constructie er omheen en je bent zeker dat je geen geheugen lekt.
    DeX 3 Delphi := The ease of VB with the power of C; Zoekt en gij zult vinden

  3. #3
    Quote Originally Posted by Henkie View Post
    Nu nog een try-finally constructie er omheen en je bent zeker dat je geen geheugen lekt.
    Yep. Bedankt.

  4. #4
    Twee vraagjes:
    ~ Wat is het verschil tussen jouw code en NLDCalcStrings?
    ~ Waarom noem je je class Eval, en niet TEval, zoals gebruikelijk is volgens de Delphi naamgevingsrichtlijnen?
    1+1=b

  5. #5
    Quote Originally Posted by GolezTrol View Post
    Twee vraagjes:
    ~ Wat is het verschil tussen jouw code en NLDCalcStrings?
    Geen idee, ik heb er niet naar gekeken.

    Nu wel gekeken (29-6-2007):
    NLCCalcstrings heeft een aantal extra zaken:
    - de "^" operator
    - de functies SIN, COS en POWER
    - normale operator voorrang (voor zover ik kan zien)
    - zelf gedefineerde functies als ik het goed heb
    - en misschien nog andere zaken die ik niet zo snel kan zien...
    - maar... ikzelf heb wel de "%" operator (percent)
    Quote Originally Posted by GolezTrol View Post
    ~ Waarom noem je je class Eval, en niet TEval, zoals gebruikelijk is volgens de Delphi naamgevingsrichtlijnen?
    Het zou uiteraard TEval moeten zijn ("Eval" is toevallig uit de testversie in de officiele geslopen). Ik zal het wijzigen (het zal waarschijnlijk "TSimpleEval" worden...) Bedankt.
    Last edited by Dany; 30-Jun-07 at 21:31.

  6. #6
    maar... ikzelf heb wel de "%" operator (percent)
    Waarom heb je die dan niet in de NLDCalcStrings gebouwd ?

  7. #7
    Quote Originally Posted by Dees View Post
    Waarom heb je die dan niet in de NLDCalcStrings gebouwd ?
    Wel,
    - NLDCalcStrings is niet van mij
    - het is gevaarlijk code aan te passen die je niet (helemaal) begrijpt.

    p.s. Ik heb het idee om de "%" operator toe te voegen in NLDCalcStrings gepost in die thread:
    http://www.nldelphi.com/Forum/showth...041#post232041
    Zie hieronder.
    Last edited by Dany; 09-Jul-07 at 17:30.

  8. #8

    "Percentage" operator

    Idee voor een extra numerieke operator: "%" (percentberekening).
    Zie ook
    http://www.nldelphi.com/Forum/showpo...30&postcount=6


    Uittreksel uit NLDCalcString:
    Code:
    Function TStringCalculator.CalcSimpleString( Const Str: String ): Double;
    Var
      Left, Right: Double;
      Operator: Char;
      I: integer;
    begin
      I := GetOperatorBefore( Str, Length(Str) );
      Operator := Str[I];
      Left  := StrToValue( Copy( Str, 1, I - 1 ));
      Right := StrToValue( Copy( Str, I+1, Length(Str) ));
    
      Case Operator of
       '+': Result := Left + right;
       '-': Result := Left - Right;
       '*': Result := Left * Right;
       '/': Result := Left / Right;
       '^': Result := Power( Left, Right );
       '%': Result := Left / Right * 100;
      end;
    end;
    Waarschijnlijk zijn nog andere kleine wijzigingen nodig.
    Last edited by Dany; 01-Jul-07 at 14:42.

  9. #9
    Hoe zou je die gebruiken dan? Ik zou verwachten dat je kunt doen:
    left * right% = right % van left = left * right / 100
    of
    left + right% = left + right% van left = left + (left * right / 100)
    1+1=b

  10. #10
    Quote Originally Posted by GolezTrol View Post
    Hoe zou je die gebruiken dan? Ik zou verwachten dat je kunt doen:
    left * right% = right % van left = left * right / 100
    of
    left + right% = left + right% van left = left + (left * right / 100)
    De Operator "%" is, zoals hier voorgesteld, geen "standaard" operator:
    "%" berekent (zoals geimplemeneerd in TSimpleEval waaruit dit voorstel komt) het percentage dat "left" is van "right" (de uitkomst is dus het "percentage"), dus niet "hoeveel is "left" percent van right" (een waarde).
    Dus "25 % 250" geeft 10 (25 is 10% van 250).

    Het is dus helemaal niet wat rekenmachines kunnen doen:
    bv "2 * 10%" geeft 0.2; ----- In simpleEval (0.1 * 2)
    of "10 + 20%" geeft 12... ----- In SimpleEval (10 + (0.2 * 10))

    p.s. De reden voor het "uitvinden" van die "%" operator is dat ik veel met expressies zoals "100 * a / b" werk.
    Last edited by Dany; 02-Jul-07 at 19:51.

  11. #11
    Counting your refs Paul-Jan's Avatar
    Join Date
    Feb 2002
    Location
    Lage Zwaluwe
    Posts
    2,160
    Ik zeg niet dat het geen goed idee is, maar mensen die ook in niet-pascal talen werken zullen een binaire % operator sterk associeren met de modulus operatie.

  12. #12
    Quote Originally Posted by Paul-Jan View Post
    Ik zeg niet dat het geen goed idee is, maar mensen die ook in niet-pascal talen werken zullen een binaire % operator sterk associeren met de modulus operatie.
    Oeps...
    Voorstel?

  13. #13
    Silly member NGLN's Avatar
    Join Date
    Aug 2004
    Location
    Werkendam
    Posts
    5,133
    Maar dit component zal vooral door Delphi gebruikers (of bekenden van) gebruikt worden, toch?

    En ik weet niet of de modulus al verwerkt is in dit component, maar anders opper ik daar de \ operator voor, ook redelijk universeel.
    Last edited by NGLN; 03-Jul-07 at 16:14. Reason: typo
    (Sender as TNLDUser).Signature := 'Groeten van Albert';

  14. #14
    of gewoon het woord 'mod'
    1+1=b

  15. #15
    mov rax,marcov; push rax marcov's Avatar
    Join Date
    Apr 2004
    Location
    Ehv, Nl
    Posts
    10,357
    De % operator brengt me wel nog op een andere uitbreiding (en zo nuttig dat zelfs windows calc het heeft):

    In mijn eigen evaluator gebruik ik % voor binaire literals, & voor octale en $ voor hexwaarden.

    Kan je al hex/bin/oct waarden in je expressies gebruiken?

Page 1 of 4 1 2 3 ... LastLast

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •