C'est un évaluateur d'expression mathématique. Vous lui donnez une chaine de caractère, il vous retourne la valeur calculée...
Il gére les opérateurs classique +-*/, mais aussi les puissances : ^ et le modulo \
Il gère également les parenthèses... à notez que si si le nombre parenthèses ouvertes et fermées sont différent, il corrige lui seul le bug... en complètant les parenthèses manquantes !!!
Il peut par exemple vous calculer : 2 * ((2^4 + 4) * 5 ) * 5 = 1000
ou 10 \ 3 = 1 (le modulo : 10 modulo 3 =1)
Source / Exemple :
Function TVARS.GetValExpr(Sender : TObject ; Value : string; posi : integer; avant : boolean) : string;
const
operation = '*/\+-^{}'; //
var
i : integer;
go : boolean;
s : string;
begin
// extrait l'expression avant=True : avant la position ou avant=false : aprés la position
if avant then
i := -1
else
i := 1;
s := '';
// condition pour continuer
go := true;
if (posi + i < 0) or (posi + i > length(Value)) then
go := false;
if Go then
Begin
// faire la boucle pour extraire la valeur à retourner
while go and ((pos(Value[posi + i], operation) < 1)) do // And (i > 1)
begin
if avant then
begin
s := Value[posi + i] + s;
dec(i);
// récupérer le signe pour faire l'opération suivante...
If Value[posi + i] = '-' then
s := '-' + s;
end
else
begin
s := s + Value[posi + i];
inc(i);
end;
if (posi + i < 0) or (posi + i > length(Value)) then
go := false;
end;
end;
// retourner la valeur
GetValExpr := s;
end;
Function TVARS.EvalExpression(Sender : TObject ; var Value : string) : string;
var
i : integer;
posi : integer;
s1, s2 : string;
// premier : boolean;
retour : string; // Valeur de retour : le résultat du calcul
startparent : integer; // position dans Value de la première parenthése ouverte
Endparent : integer; // position dans Value de la parenthése fermée
ouvreparent : integer; // nombre de parenthèses ouvertes
fermeparent : integer; // nombre de parenthèses fermées
begin
// Auteur : fabien FERT ==> adress Mail : fabien.fert@wanadoo.fr
// version 0.8 : 11/07/2004 : gestion d'un calcul unique (suppressions des espaces sur les valeur retournées avant le calcul)
// version 0.9 : 17/07/2004 : gestion de plusieurs calculs cumulés
// version 1.0 : 17/07/2004 : gestion des parenthèses
// version 1.1 : 19/07/2004 : gestion des espaces (début et fin de chaîne) : Erreur soulevée par Japee sur www.delphifr.com
// version 1.2 : 25/07/2004 : Remplacement des () par les {} pour la compatibilité SQL
// version 1.3 : 30/07/2004 : Correction Bug - comme signe rencontré dans les expressions : -{-0.1-2}, -2+1, 3-{4-3*4}, 5+{-2}, 1+125+{25-36}
// version 1.4 : 12/08/2004 : Correstion Bug - Ln{2} = Ln0
// TODO : gestion des fonctions : Sin, cos, Tan, Exp, Ln, 1/n, Sqr
// vous pouvez réutilisez ce code à votre guise à condition de ne pas effacer les lignes ci-dessus.
// Premier := false; // le premier chiffre est finit ? : non // Attention suppression à vérifier !!!
s1 := '';
s2 := '';
// vérifie que toutes les parenthèse ouvertes sont fermées...
i := 1;
Value := Trim(Value);
ouvreparent := 0;
fermeparent := 0;
while i < length(Value)+1 do
begin
if Value[i] = '{' then
begin
inc(ouvreparent);
end
else if Value[i] = '}' then
begin
inc(fermeparent);
end;
inc(i);
end;
// s'il y a un problème de paranthése : on complète ( en début ou ) à la fin
if ouvreparent > fermeparent then
begin
i := 0;
while i < ouvreparent-fermeparent Do
begin
Value := Value + '}';
inc(i);
end;
end
else if ouvreparent < fermeparent then
begin
// ouvre la parenthése
for i := ouvreparent to fermeparent Do
begin
Value := '{' + Value;
end;
end;
// Gére les parenthèse ou les reste....
if pos('{', Value) > 0 then
Begin
// s'il y a des parenthèse on les gère ici
// faire un appel récursif du contenu des parenthèses
startParent := 0;
EndParent := 0;
ouvreparent :=0;
fermeparent :=0;
i := 1;
while i < length(Value)+1 do
begin
if Value[i] = '{' then
begin
inc(ouvreparent);
If StartParent = 0 then StartParent := i;
end
else if Value[i] = '}' then
begin
inc(fermeparent);
If (endParent = 0) and (fermeparent = ouvreparent) then EndParent := i;
end;
inc(i);
end;
// Evaluer la chaine contenue dans les parenthèses
if StartParent + 1 <= EndParent - 1 Then
begin
Retour := copy(Value, startParent + 1, EndParent -1 - startparent);
EvalExpression(Sender, Retour);
end
else
retour := '0';
// concaténé le resultat
if (EndParent + 1 < Length(Value)) and (StartParent > 0) then
Value := copy(Value, 0, StartParent -1) + retour + copy(Value, EndParent+1, length(value))
else if startParent = 0 then
Value := retour + copy(Value, EndParent+1, length(value))
else if (EndParent + 1 > Length(Value)) then
Value := copy(Value, 0, StartParent -1) + retour;
// faire un appel récursif pour évaluer la chaine résultante
EvalExpression(Sender, Value);
end
else if pos('@', uppercase(Value)) > 0 then
begin
{ PAS UTILISE ICI : sert pour l'exécution de fonctions : envois de Mail, Liste les variables, exécuter des applications extérieures, etc... fonctions avancées...
// retourner l'expression littérale... si elle contient des lettres de l'alphabet
posi := pos('@', Value);
Value := VarEvalFunction(Sender, Value);
}
end
else if pos('$', uppercase(Value)) > 0 then
begin
{ PAS UTILISE ICI : Sert pour la gestion des variables interne
// retourner l'expression littérale... si elle contient des lettres de l'alphabet
posi := pos('$', Value);
s1 := GetVarName(sender, Value);
// affecte et retourne la valeur....
Value := GetVarStrAffect(Sender, copy(Value, pos(s1, uppercase(Value)) + length(s1), length(Value)), s1);
// supprimer l'affectation si il y a lieu
// Value := copy(Value, 0, pos(s1, uppercase(Value)) + length(s1)) + Copy(Value, pos(s1, uppercase(Value)) + length(s1) + posi2, length(Value));
}
end
else if pos('A', uppercase(Value)) + pos('B', uppercase(Value)) + pos('C', uppercase(Value)) + pos('D', uppercase(Value)) + pos('E', uppercase(Value)) + pos('F', uppercase(Value)) + pos('G', uppercase(Value)) + pos('H', uppercase(Value)) + pos('I', uppercase(Value)) + pos('J', uppercase(Value)) + pos('K', uppercase(Value)) + pos('L', uppercase(Value)) + pos('M', uppercase(Value)) + pos('N', uppercase(Value)) + pos('O', uppercase(Value)) + pos('P', uppercase(Value)) + pos('Q', uppercase(Value)) + pos('R', uppercase(Value)) + pos('S', uppercase(Value)) + pos('T', uppercase(Value)) + pos('U', uppercase(Value)) + pos('V', uppercase(Value)) + pos('W', uppercase(Value)) + pos('X', uppercase(Value)) + pos('Y', uppercase(Value)) + pos('Z', uppercase(Value)) + pos('"', uppercase(Value)) + pos(':', uppercase(Value)) + pos('=', uppercase(Value)) > 0 then
begin
// retourner l'expression littérale... si elle contient des lettres de l'alphabet
Value := Value;
end
else if pos('*', Value) + pos('/', Value) + pos('\', Value) + pos('+', Value) + pos('-', Value) + pos('^', Value) > 0 then
begin
if pos('^', Value) > 0 then
begin
// extraire la partie droite et gauche du signe
posi := pos('^', Value);
s1 := GetValExpr(sender, Value, posi, True);
If Value[Posi + 1] = '-' then
Begin
Value[Posi + 1] := '0';
s2 := '-' + GetValExpr(sender, Value, posi, False);
end
Else
Begin
s2 := GetValExpr(sender, Value, posi, False);
End;
retour := FloatToStr(Power(strToFloat(trim(s1)),strToFloat(trim(s2))));
// remplacer la valeur
s1 := s1 + '^' + s2;
Value := copy(Value, 0, pos(s1, Value) -1) + retour + copy(Value, pos(s1, Value) + length(s1), length(value));
// faire un appel récursif
EvalExpression(Sender, Value);
end
else if pos('*', Value) > 0 then
begin
// extraire la partie droite et gauche du signe
posi := pos('*', Value);
s1 := GetValExpr(sender, Value, posi, True);
If Value[Posi + 1] = '-' then
Begin
Value[Posi + 1] := '0';
s2 := '-' + GetValExpr(sender, Value, posi, False);
end
Else
Begin
s2 := GetValExpr(sender, Value, posi, False);
End;
retour := FloatToStr(strToFloat(trim(s1)) * strToFloat(trim(s2)));
// remplacer la valeur
s1 := s1 + '*' + s2;
Value := copy(Value, 0, pos(s1, Value) -1) + retour + copy(Value, pos(s1, Value) + length(s1), length(value));
// faire un appel récursif
EvalExpression(Sender, Value);
end
else if pos('/', Value) > 0 then
begin
// extraire la partie droite et gauche du signe
posi := pos('/', Value);
s1 := GetValExpr(sender, Value, posi, True);
If Value[Posi + 1] = '-' then
Begin
Value[Posi + 1] := '0';
s2 := '-' + GetValExpr(sender, Value, posi, False);
end
Else
Begin
s2 := GetValExpr(sender, Value, posi, False);
End;
if (s2 <> '0') and (s2 <> '-0') then
retour := FloatToStr(strToFloat(trim(s1)) / strToFloat(trim(s2)))
else
retour := '0';
// remplacer la valeur
s1 := s1 + '/' + s2;
Value := copy(Value, 0, pos(s1, Value) -1) + retour + copy(Value, pos(s1, Value) + length(s1) , length(value));
// faire un appel récursif
EvalExpression(Sender, Value);
end
else if pos('\', Value) > 0 then
begin
// extraire la partie droite et gauche du signe
posi := pos('\', Value);
s1 := GetValExpr(sender, Value, posi, True);
If Value[Posi + 1] = '-' then
Begin
Value[Posi + 1] := '0';
s2 := '-' + GetValExpr(sender, Value, posi, False);
end
Else
Begin
s2 := GetValExpr(sender, Value, posi, False);
End;
retour := FloatToStr(strToint(trim(s1)) Mod strToint(trim(s2))); // calcule le modulo 10 mod 3=1
// remplacer la valeur
s1 := s1 + '\' + s2;
Value := copy(Value, 0, pos(s1, Value) -1) + retour + copy(Value, pos(s1, Value) + length(s1) , length(value));
// faire un appel récursif
EvalExpression(Sender, Value);
end
else if pos('+', Value) > 0 then
begin
// extraire la partie droite et gauche du signe
posi := pos('+', Value);
s1 := GetValExpr(sender, Value, posi, True);
If Value[Posi + 1] = '-' then
Begin
Value[Posi + 1] := '0';
s2 := '-' + GetValExpr(sender, Value, posi, False);
end
Else
Begin
s2 := GetValExpr(sender, Value, posi, False);
End;
retour := FloatToStr(strToFloat(trim(s1)) + strToFloat(trim(s2)));
// remplacer la valeur
s1 := s1 + '+' + s2;
Value := copy(Value, 0, pos(s1, Value) -1) + retour + copy(Value, pos(s1, Value) + length(s1) , length(value));
// faire un appel récursif
EvalExpression(Sender, Value);
end
else if pos('-', Value) > 0 then
begin
// extraire la partie droite et gauche du signe
posi := pos('-', Value);
If posi = 1 then
posi := 1 + pos('-', Copy(Value,2, length(Value)));
// ne pas compter le permier signe..
if posi > 1 then
begin
// si c'est bien une opération (pas le signe de la valeur résultat) : on peut calculer...
s1 := GetValExpr(sender, Value, posi, True);
If Value[Posi + 1] = '-' then
Begin
Value[Posi + 1] := '0';
s2 := GetValExpr(sender, Value, posi, False);
end
Else
Begin
s2 := GetValExpr(sender, Value, posi, False);
End;
If s1 <> '' then
begin
retour := FloatToStr(strToFloat(trim(s1)) - strToFloat(trim(s2)));
// remplacer la valeur
s1 := s1 + '-' + s2;
Value := copy(Value, 0, pos(s1, Value) -1) + retour + copy(Value, pos(s1, Value) + length(s1) , length(value));
// faire un appel récursif
EvalExpression(Sender, Value);
end;
end
end;
// Gérer le double Signe - du départ : le supprimer
If Value[1] = '-' then
If Value[2] = '-' then
Value := '-' + Copy(Value, 3, length(Value)); // := '0';
end;
// Retourner la valeur
EvalExpression := Value;
end;
Conclusion :
L'appel de l'évaluateur se fait de la façon suivante :
resultat.Caption := ListeVar.EvalExpression('2*((2^4+4)*5)*5');
NOTA : le résultat retourné est une chaine de caractère... pour l'utiliser en numérique il faut la convertir...
NOTA 2 : Pour la compatibilité avec l'ensemble de composants que je suis en train de développer, j'ai été obligé de remplacer les () par des {}.... Donc pensez à utiliser les {} au lieu des () sinon Erreur !!! (car j'utilise cette évaluateur d'expression dans des requêtes SQL....)... Merci de votre comprehension et désolé pour ce petit désagrément, remplacer simplement les {} par des () pour une utilisation normale
Tous les BUG connus sont Corrigés dans cette source.... (merci Japee, GrandVizir, xoleras, pyroflo)
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.