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
Bookmarks