Calculatrice de chaines mathématiques

5/5 (11 avis)

Vue 13 209 fois - Téléchargée 902 fois

Description

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.

Codes Sources

A voir également

Ajouter un commentaire Commentaires
HAFTARIFOUAD Messages postés 256 Date d'inscription mercredi 5 septembre 2007 Statut Membre Dernière intervention 6 janvier 2011
28 janv. 2008 à 16:03
Salut ;-)

Trés bon votre code
Voilà je veux juste vous souhaiter bonne continuation.
Oniria Messages postés 292 Date d'inscription dimanche 14 mars 2004 Statut Membre Dernière intervention 18 décembre 2014 3
28 janv. 2008 à 16:08
Bonjour,

Merci beaucoup, et toi de même...
cs_jeanr Messages postés 17 Date d'inscription vendredi 25 avril 2003 Statut Membre Dernière intervention 12 juin 2008
29 janv. 2008 à 07:22
Bon source :-)
cs_barbichette Messages postés 220 Date d'inscription lundi 30 octobre 2000 Statut Membre Dernière intervention 15 juillet 2013
7 févr. 2008 à 11:34
je viens de voir un petit bug.
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;
kevinou55 Messages postés 15 Date d'inscription mardi 5 juin 2007 Statut Membre Dernière intervention 12 février 2008
12 févr. 2008 à 11:20
J'ai trouvé une solution pour le 2(5+8) !!! lol
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.