Ce petit programme montre comment utiliser l'unité expression contenu dans le zip.
Il peut donc calculer des chaines mathématiques tels que : (10+2*3)-5*sin(60)
Il respecte les priorités des opérateurs, fait les calculs dans les parenthèses avant les autres.
Il est sans prétension mais permet de comprendre comment ajouter dans un programme la faculté de calculer des expressions mathématiques. Je me suis basé d'une source parue dans Pascalissime. Ça fait très longtemps que j'ai fait ce source mais je pense qu'il peut intéresser quelques personnes.
Conclusion :
Je suis ouvert à toutes vos suggestions pertinentes.
28 janv. 2008 à 16:03
Trés bon votre code
Voilà je veux juste vous souhaiter bonne continuation.
28 janv. 2008 à 16:08
Merci beaucoup, et toi de même...
29 janv. 2008 à 07:22
7 févr. 2008 à 11:34
Losque la chaine commence par un signe - suivi d'une fonction
ex : "-cos(10)" ou encore "2*(-exp(10))"
Ou encore "3-cos" <= oubli d'une valeur après
il y a bug car le programme essai de faire ça :
pilval[-1]:=pilval[-1]-pilval[0]; <== indice en dehors des limites.
donc
il faut toujours vérifier que pilval contient toujours assez de valeur pour faire les opérations.
Je sais que ce bout de code ne vient pas de toi, mais voilà une version un peu modifiée avec des tests en moins et l'utilisation de l'opérateur "in"
sinon, c'est formidable comme performance en si peu de lignes.
barbichette
//******************************************************************************
// Cette fonction a été récupérée dans la revue Pascalissime
// elle permet d'effectuer les calculs simples sans parenthéses.
// ex : 10*25+4E-3-s10
// ici s est la simplification de sin (fonction sinus)
//******************************************************************************
Function Evalu_exp( gisp : string ) : real;
VAR giap : string;
g_postfix : array[0..255] of string;
lip,lpp : integer; // index dans infix, index dans g_postfixe
l_indice,indval,l_base : integer;
pilval : array[0..255] of real;
symb : char;
BEGIN
// convertis_infix_en_postfix
// La notation infix est celle utilisée couramment en math
// par exemple A+(B-C)
// la notation postfix nous donne pour cet exemple ABC-+
// Cette notation fait intervenir la notion de pile.
// donc ABC-+ sera calculé de la facon suivante:
// le premier caractére est A : mise sur la pile
// le deuxiéme est B : mise sur la pile
// le troisieme est C : mise sur la pile
// le quatrieme est - : dépile C et B, on effectue B-C puis le résultat est remis dans la pile.
// appelons B-C la valeur D=B-C (juste pour la comprehension)
// la pile resemble à : A D +
// la cinquiéme étape est + : on dépile D et A, on calcule A+D puis le résultat est remis dans la pile
// a ce moment, la pile ne contient plus qu'un élément c'est le résultat R
//
// La conversion se fait avec les prioritées de chaque opérateur.
// convertion de la chaine en un tableau de valeur ou de propriete
giap:='';
l_base:=0;
gisp:=gisp+'z';
FOR l_indice:=1 TO length(gisp) do
Begin
// si on a un chiffre (éventuellement avec un - ou un + devant),
if (gisp[l_indice] in ['0'..'9','E','.',','])
or ((l_indice=1) and (gisp[1]='-'))
or ((l_indice>1) and (gisp[l_indice]='-') and not (gisp[l_indice-1] in ['0'..'9']))
or ((l_indice>1) and (gisp[l_indice]='+') and (gisp[l_indice-1]='E')) then
begin
giap:=giap+gisp[l_indice];
end
else
// sinon, c'est un opérateur
begin
// si il y avait un chiffre en attente, on le sauve dans infix
if giap<>'' then
begin
infix[l_base].priorite:=6;
infix[l_base].texte:=giap;
giap:='';
l_base:=l_base+1;
end;
// on sauve l'opérateur dans infix
infix[l_base].priorite:=g_priorite[gisp[l_indice]];
infix[l_base].texte:=gisp[l_indice];
l_base:=l_base+1;
end;
// au dernier tour, si il y a un nombre en attente dans gaip, on le sauve dans infix
if (giap<>'') and (l_indice=length(gisp)) then
begin
infix[l_base].priorite:=6;
infix[l_base].texte:=giap;
l_base:=l_base+1;
end;
end;
l_pile[0].texte:='%';
l_pile[0].priorite:=1;
lip:=0;
lpp:=0;
giap:='';
g_postfix[0]:='';
FOR l_indice:=0 TO l_base-1 do
Begin
if l_pile[lip].priorite>infix[l_indice].priorite then
while l_pile[lip].priorite>=infix[l_indice].priorite do
begin
g_postfix[lpp]:=l_pile[lip].texte;
lip:=lip-1;
lpp:=lpp+1;
end;
lip:=lip+1;
l_pile[lip].texte:=infix[l_indice].texte;
l_pile[lip].priorite:=infix[l_indice].priorite;
end;
// evalue_postfix
indval:=-1;
for l_indice:=0 to lpp-1 do
begin
if (length(g_postfix[l_indice])=1) and
not (g_postfix[l_indice][1] in ['0'..'9']) then
begin
symb:=g_postfix[l_indice,1];
if (symb in ['+','-','*','/','^']) and (indval<1) then exit;
if not (symb in ['+','-','*','/','^']) and (indval<0) then exit;
case symb of
'+' : pilval[indval-1]:=pilval[indval-1]+pilval[indval];
'-' : pilval[indval-1]:=pilval[indval-1]-pilval[indval];
'*' : pilval[indval-1]:=pilval[indval-1]*pilval[indval];
'/' : pilval[indval-1]:=pilval[indval-1]/pilval[indval];
'^' : if pilval[indval-1]>0
then pilval[indval-1]:=exp(pilval[indval]*ln(pilval[indval-1]))
else pilval[indval-1]:=1;
's' : pilval[indval]:=sin(pilval[indval]); {sin}
'c' : pilval[indval]:=cos(pilval[indval]); {cos}
't' : pilval[indval]:=tan(pilval[indval]); {tan}
'l' : pilval[indval]:=log10(pilval[indval]); {log}
'r' : pilval[indval]:=arcsin(pilval[indval]); {arcsin}
'm' : pilval[indval]:=arccos(pilval[indval]); {arccos}
'n' : pilval[indval]:=arctan(pilval[indval]); {arctan}
'o' : pilval[indval]:=ln(pilval[indval]); {ln}
'p' : pilval[indval]:=exp(pilval[indval]); {exp}
'q' : pilval[indval]:=sqrt(pilval[indval]); {racine carré}
end;
// opérateur à 2 opérandes
if symb in['+','-','*','/','^'] then dec(indval);
end else
begin
inc(indval);
pilval[indval]:=StrToFloat(g_postfix[l_indice]);
end;
end;
Evalu_exp:=pilval[0];
end;
12 févr. 2008 à 11:20
au tout debut de ta fonction eval, lorsque tu compte le nombre de parentheses ouvrantes et fermantes:
deja il au faire un Repeat-- Until ensuite
il faut tester d'abord les parentheses fermantes puis dans le test des ouvrantes tu regarde si le caractère précédent est un nombre.
Si c'est le cas tu ajoute un '*' avant et tu incremente i une fois de plus
En gros tu fais comme ca lol (encore desolé pour les variables)
i:=1;
Repeat
if (strTemp[i]=')')
then begin
parant_droite:=parant_droite+1;
strTemp[i]:=')';
end;
if (strTemp[i]='(')
then begin
strTemp[i]:='(';
parant_gauche:=parant_gauche+1;
if strTemp[i-1] in ['0'..'9'] //si le caractère precedent est un nombre
then begin
//on prend la partie avant la prenthese on ajoute '*' puis le reste
strTemp:=copy(strTemp,0,i-1)+'*'+copy(strTemp,i,length(strTemp)-i+1);
//il faut incrementer i car sinon la parenthes est comptée 2 fois
inc(i);
end;
end;
strTemp[i]:=upcase(strTemp[i]); //on met en majuscules
inc(i);
until i>Length(strTemp);
En esperant que vous ne trouverez pa de bugs ;)
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.