Mini evaluateur d'expression arithmétiques

Soyez le premier à donner votre avis sur cette source.

Vue 15 252 fois - Téléchargée 1 471 fois

Description

Cette mini classe permet d'évaluer des expressions arithmétiques. Calcule sur des reels (double) et il y a que les opérations suivantes : plus,moins, multiplier,diviser,parentheses,sin,cos.

On peut aussi utiliser des variables

Se base sur la théorie des langages! utilise un analyseur syntaxique qui permet de calculer une expression a partir d'une grammaire.

Pour évaluer l'expression, on utilise une pile.

Voici la grammaire :
S' -> E
E -> TE'
E' -> +TE'
E' -> -TE'
E' -> $
T -> FT'
T' -> *FT'
T' -> /FT'
T' -> $
F -> id
F -> (E)

En modifiant légérement la grammaire on peut trés facilement gerer les nombres a virgules (voir dans la méthode F)

La grammaire et la source ont été inspirés du cours de M. Krajecki disponible a l'adresse suivante :

http://cosy.univ-reims.fr/~mkrajecki/enseignement/info62/info62Chap3.pdf

Source / Exemple :


//utilisation :
//on instancie 
Evalueur e=new Evalueur();

//on évalue une expression
double r=e.evalue("2*5+10");

//le résultat n'est valable que si getErreur() ne renvoi pas d'erreur
if (e.getErreur()==Evalueur.NO_ERROR)
 System.out.println("resultat : "+r);
else
 System.out.println("Erreur de syntaxe");

NOUVEAU MAJ : on peut mettre des variables et utiliser des fonctions prédéfinies (sin et cos)

Pour evaluer une expression avec une variable :
e.addVar("x",5.0);
e.evalue("2.5*x");

Pour utiliser sin ou cos :
e.evalue("cos(2.0)");
e.evalue("cos(2.0*x+5.0)+2");
e.evalue("sin(2.0)");

NOUVEAU : Si l'expression ne change pas, on peut optimiser l'évaluation de l'expression avec reevalue :
-la 1ere fois, utiliser evalue pour calculer la formule (genere l'expression)
e.addVar("x",5.0);
e.evalue("cos(x)");
-ensuite, on peut utiliser reevalue qui rejoue la derniere expression mais en prenant compte tout de meme des variables modifiées :
e.addVar("x",15.0);
e.reevalue();

L'execution de reevalue est plus rapide que evalue car reevalue réutilise la pile de fonctions générée par evalue

Tout simplement! :)

Conclusion :


1) Je sais qu'une autre source pour évaluer des expression est disponible mais la mienne me parait interressante a publier aussi car elle montre l'utilisation de grammaire (utilisé pour faire par exemple des compilateur (c'est génial a faire ;) )). ça peut aider certain qui auront un point de départ pour comprendre les grammaires (ça peut aider en Master info par exemple!! lol)

2) Un exemple d'utilisation est inclus

Sous Windows, pour lancer le test : executez le script run.bat
executez compile.bat pour compiler les classes

En ligne de commande :
Pour executer : tapez java TestEvalueur
Pour compiler : tapez javac *.java

Codes Sources

A voir également

Ajouter un commentaire Commentaires
Messages postés
5
Date d'inscription
samedi 20 octobre 2012
Statut
Membre
Dernière intervention
1 juin 2013

Désolé du retard..

Oui, effectivement, il ya une erreur
étant donné que tu n'herite plus de Fonction, il ne reconnait pas vu que empileF n'empile que des fonctions de type "Fonction" et vu que l'heritage multiple n'existe pas en java, je te conseillerais de creer une interface pour ça...
ensuite tu fais ta fonctionPlus implements Fontion.. ça peut marcher ;)

Moi j'ai une autre erreur qui concerne la fonctionPow donc pour le calcul de la puissance...
comment dire ou modifier la grammaire pour que la fonction puissance soit prioritaire par rapport aux fonctions... car 2^2*3^2 ne fait pas 144 mais 36 !!!!
J'ai essayé d'ajouter un int de priorité mais je ne comprends pas comment le passer lors de l'evaluation de l'expression qui peut contenir un calcul de puissance ou peut ne pas en contenir..
Voilà
Merci de votre aide
Messages postés
74
Date d'inscription
vendredi 27 juin 2008
Statut
Membre
Dernière intervention
1 juin 2013

salut agent24,j'ai essayé ce que tu as dit mais j'ai un soucis sur ces differents methodes que voici:
l'instanciation FonctionPlus genère une erreur dans cette fonction empileF(new FonctionPlus()),c'est logique car FonctionPlus ne fait plus partir de la classe Evalueur et herite de Evalueur. pareil pour empileF(new FonctionMoins())...
private void Eprime()
{
if (erreur!=ERROR_NO) return;

if (lu=='+')
{
avance(); T(); empileF(new FonctionPlus()); Eprime();

}else if (lu=='-')
{
avance(); T(); empileF(new FonctionMoins()); Eprime();

}
}

/**
* T->FT'
*/
private void T()
{
if (erreur!=ERROR_NO) return;

if (lu=='(' || (lu>='0' && lu<='9') || (lu>='a' && lu<='z') || (lu>='A' && lu<='Z'))
{
F(); Tprime();
}else erreur=ERROR_BAD_SYNTAX;
}

/**
* T'->*FT' | /FT' | $
*/
private void Tprime()
{
if (erreur!=ERROR_NO) return;
if (lu=='*')
{
avance(); F(); empileF(new FonctionMulu()); Tprime();

}else if (lu=='/')
{
avance(); F(); empileF(new FonctionDiv()); Tprime();

}

}

/**
* F->id | (E)
*/
private void F()
{
if (erreur!=ERROR_NO) return;
if (lu>='0' && lu<='9')
{
double valeur=0;
while(lu>='0' && lu<='9') //lit une valeur numérique
{
valeur=valeur*10+(lu-'0');
avance();
}
if (lu=='.') //reel
{
avance();
double av=0.1;
while(lu>='0' && lu<='9') //lit une valeur numérique
{
valeur=valeur+(lu-'0')*av;
av=av*0.1;
avance();
}
}
empileF(new FonctionCst(valeur));
}else if ((lu>='a' && lu<='z') || (lu>='A' && lu<='Z')) //une variable
{
String nomv=""+lu;
avance();
while((lu>='a' && lu<='z') || (lu>='A' && lu<='Z') || (lu>='0' && lu<='9'))
{
nomv=nomv+lu;
avance();
}
if (lu!='(') //c'est une variable
{
//cherche la variable
Double var=vars.get(nomv);
if (var==null)
erreur=this.ERROR_UNKNOW_VAR;
else
empileF(new FonctionVar(nomv));
}else
{ //une fonction
avance();
E();
if (lu==')')
avance();
else erreur=ERROR_BAD_SYNTAX;

if (nomv.equals("sin")) //sinus
empileF(new FonctionSin());
else if (nomv.equals("cos")) //cos
empileF(new FonctionCos());
else
erreur=this.ERROR_UNKNOW_FUNCTION;
}
}
else if (lu=='(')
{
avance();
E();
if (lu==')')
avance();
else erreur=ERROR_BAD_SYNTAX;
}else erreur=ERROR_BAD_SYNTAX;
}
Messages postés
5
Date d'inscription
samedi 20 octobre 2012
Statut
Membre
Dernière intervention
1 juin 2013

Slt tout le monde !!
POur ta question de séparer en différentes classes Lemufty,... je pense que tu dois faire un extends de Evalueur pour chaque fonction, et la dans evalue de tes fonctions, tu fais super.depile(); pour bien récuperer la dernière valeur contenue dans la pile...
J'ai peut être tort mais ça ne coûte rien d'essayer...
Messages postés
74
Date d'inscription
vendredi 27 juin 2008
Statut
Membre
Dernière intervention
1 juin 2013

jai vu comment utiliser la fonction addVar().
Messages postés
74
Date d'inscription
vendredi 27 juin 2008
Statut
Membre
Dernière intervention
1 juin 2013

jai voulu separer les classes interne qui sont dans Evalueur telle que FonctionFois,FonctionPlus,FonctionMoins et jai transformé la classe Fonction en interface .mais quand j'execute le main j'obtiens à chaque fois 0.0.voici des bouts de mon code.quelqu'un a t'il une idée car je voudrais separer les classes et non les condenser toutes dans Evalueur.merci

public class FonctionPlus extends Evalueur implements Fonctionabl{

@Override
public void evalue() {
empile(depile()+depile());
}
public String toString()
{
return "+";
}



}
public interface Fonctionable {


public void evalue();

}
Afficher les 19 commentaires

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.