diff --git a/src/net/mc_pandacraft/java/util/JArithmeticInterpreter.java b/src/net/mc_pandacraft/java/util/JArithmeticInterpreter.java new file mode 100644 index 0000000..add9378 --- /dev/null +++ b/src/net/mc_pandacraft/java/util/JArithmeticInterpreter.java @@ -0,0 +1,761 @@ +package net.mc_pandacraft.java.util; + +//****************************************************************************** +//*** +//*** INTERPRETEUR ARITHMETIQUE version 2.1 Version Java +//*** +//*** +//*** +//****************************************************************************** + +/* +Historique: + +2.1: + - Version Java disponible: + # les operateurs mathematiques disponibles sont ceux de Java donc certains manquent. + +2.0: + - Portage en C++ et debut en Java + +Version C++: + + - Meilleure gestion memoire lors de la construction de l'expression. + - Acceleration de certaines operations. + +Version Java: + + - Premiere version. Normalement ca doit marcher + +1.3b: ajoute les fonctions suivantes: (NON DISTRIBUEE) + - reconnaissance du symbole � + - ecriture formatee d'expression (� ameliorer) + +1.2: corrige les bugs suivants: + - erreur sur l'interpretation de fonctions unaires imbriquees telles que ln(exp(x)). + - la fonction puissance (pour les puissances entieres). + ajoute: + - la verification de la chaine entree (voir code d'erreur) + - la verification de l'existence de l'evaluation (voir code d'erreur) + + +1.1: corrige un bug au niveau de l'interpretation des fonctions du type: + + exp(-(x+y)) + +1.0: premiere version + +Le code source peut etre librement modifie et distribue. + +Puisqu'il s'agit d'un essai en Java, le code ne doit pas etre super genial et merite sans doute +quelques modifications.En particulier, il serait interessant de rajouter le support des Exceptions +pour les calculs (division par zero, etc...). + +*/ + +// Classe servant � palier l'absence de passage par variables ou reference + +class VariableInt { + public int mValue; +} + +// Classe principale + +public class JArithmeticInterpreter { + + // Variables + + int mOperator; + double mValue; + JArithmeticInterpreter fg, fd; + + // Methods + + //.................................................................................... Node + + private JArithmeticInterpreter() { + this(0, 0, null, null); + } + + //.................................................................................... Node + + private JArithmeticInterpreter(int Operator,double Value,JArithmeticInterpreter Fg,JArithmeticInterpreter Fd) { + mOperator=Operator; + mValue=Value; + fg=Fg; + fd=Fd; + } + + private JArithmeticInterpreter(int Operator,double Value) { + this(Operator, Value, null, null); + } + + //.................................................................................... Construct_Tree + + private static JArithmeticInterpreter constructTree(StringBuffer string,int length,int error) { + int imbric,Bimbric; + int priorite,ope; + int position,positionv,i,j; + int opetemp=0; + int espa=0,espat=0; + int caspp=0; + + JArithmeticInterpreter node; + + // Initialisation des variables + + if (length<=0) { + error=3; + return null; + } + + ope=0; + imbric=0;Bimbric=128; + priorite=6; + i=0; + positionv=position=0; + + // Mise en place des donnees sur le morceau de chaine + + while (i47) && (string.charAt(i)<58)) || (string.charAt(i)=='�')) { + if (priorite>5) { + priorite=5; + positionv=i; + } + i++; + } + else { + if ((string.charAt(i)>96) && (string.charAt(i)<117)) { + VariableInt Vopetemp,Vespat; + + Vopetemp= new VariableInt(); + Vespat= new VariableInt(); + + Vopetemp.mValue=opetemp; + Vespat.mValue=espat; + + FindOperator(Vopetemp,Vespat,string,i); + + opetemp=Vopetemp.mValue; + espat=Vespat.mValue; + + if (opetemp>=0) { + if (imbric=4)) { + ope=opetemp; + position=i; + priorite=4; + espa=espat; + } + j=i+1; + i+=espat; + while(j=1)) { + priorite=1; + ope=1; + position=i; + caspp=0; + } + i++; + break; + case '-': + if (imbric5) { + priorite=1; + position=i; + ope=2; + Bimbric=imbric; + caspp=1; + } + } + else if (string.charAt(i-1)=='(') { + if (priorite>1){ + priorite=1; + position=i; + Bimbric=imbric; + caspp=1; + ope=2; + } + } + else { + Bimbric=imbric; + priorite=1; + ope=2; + position=i; + caspp=0; + } + } + else if ((imbric==Bimbric) && (priorite>=1)) { + if ((i-1)<0) { + if (priorite>5) { + priorite=1; + position=i; + ope=2; + caspp=1; + } + } + else if (string.charAt(i-1)=='(') { + if (priorite>1){ + priorite=1; + position=i; + caspp=1; + ope=2; + } + } + else { + priorite=1; + ope=2; + position=i; + caspp=0; + } + } + i++; + break; + case '*': + if (imbric=2)) { + priorite=2; + ope=3; + position=i; + } + i++; + break; + case '/': + if (imbric=2)) { + priorite=2; + ope=4; + position=i; + } + i++; + break; + case '^': + if (imbric=3)) { + priorite=3; + ope=5; + position=i; + } + i++; + break; + case '.': + i++; + break; + default: + error=2; // symbole non reconnu + return null; + } + } + } + } + + if (imbric!=0) { + error=1; // erreur de "parenthesage" + return null; + } + + // Traitement des donnees + + if (priorite==6) { + node =new JArithmeticInterpreter(ope,0.0); + return node; + } + else if (caspp==1) { + node = new JArithmeticInterpreter(2,0); + + node.fg= new JArithmeticInterpreter(0,0); + node.fd= new JArithmeticInterpreter(); + + if ((length-position-1-Bimbric)==0) { // argument absent + error=3; + return null; + } + StringBuffer temp=CopyPartialString(string,(position+1),(length-1-Bimbric)); + node.fd=constructTree(temp,(length-position-1-Bimbric),error); + + return node; + } + + else if (priorite==5) { + node = new JArithmeticInterpreter(0,calc_const(string,positionv),null,null); + + return node; + } + else if (ope>5) { + node = new JArithmeticInterpreter(ope,0,null,null); + + if ((length-position-espa-Bimbric)==0) { // argument absent + error=3; + return null; + } + StringBuffer temp=CopyPartialString(string,(position+espa),(length-1)); + node.fg=constructTree(temp,(length-position-espa-Bimbric),error); + return node; + } + else{ + node = new JArithmeticInterpreter(ope,0,null,null); + + if ((position-Bimbric)==0) { // argument absent + error=3; + return null; + } + StringBuffer temp=CopyPartialString(string,Bimbric,(position-1)); + node.fg=constructTree(temp,(position-Bimbric),error); + if ((length-position-1-Bimbric)==0) { // argument absent + error=3; + return null; + } + temp=CopyPartialString(string,(position+1),(length-1-Bimbric)); + node.fd=constructTree(temp,(length-position-1-Bimbric),error); + return node; + } + } + + //.................................................................................... + + private double computeTree() { + if (mOperator==0) return mValue; + int error = 0; + + double valueL=fg.computeTree(); + + if (error!=0) return 0; + double valueR=0; + + if (fd!=null) valueR=fd.computeTree(); + if (error!=0) return 0; + + switch(mOperator) { + case 1: // + + return (valueL+valueR); + case 2: // - + return (valueL-valueR); + case 3: // * + return (valueL*valueR); + case 4: // - + if (valueR==0) { + error=1; + return 0; + } + return (valueL/valueR); + case 5: // ^ + return Math.pow(valueL,valueR); + case 6: // exp + return Math.exp(valueL); + case 7: // ln + if (valueL<=0) { + if (valueL<0) error=2; + else error=1; + return 0; + } + return (Math.log(valueL)/Math.log(2)); + case 8: // log + if (valueL<=0) { + if (valueL<0) error=2; + else error=1; + return 0; + } + return Math.log(valueL); + case 9: // sqrt + if (valueL<0) { + error=2; + return 0; + } + return Math.sqrt(valueL); + case 10: // abs + return Math.abs(valueL); + case 11: + return Math.sin(valueL); // sin + case 12: + return Math.cos(valueL); // cos + case 13: + return Math.tan(valueL); // tan + case 14: + return Math.asin(valueL); // asin + case 15: + return Math.acos(valueL); // acos + case 16: + return Math.atan(valueL); // atan + default: + return 0; + } + } + + //.................................................................................... Write_Tree + + private void writeTree(StringBuffer string) { + boolean parenthese=false; + + switch(mOperator) { + case -2: + string.append('y'); + break; + case -1: + string.append('x'); + break; + case 0: + string.append(mValue); + break; + case 1: + fg.writeTree(string); + string.append('+'); + fd.writeTree(string); + break; + case 2: + if ((fg.mOperator==0) && (fg.mValue==0)); + else fg.writeTree(string); + string.append('-'); + if ((fd.mOperator==1) || (fd.mOperator==2)) { + parenthese=true; + string.append('('); + } + fd.writeTree(string); + if (parenthese==true) { + string.append(')'); + } + break; + case 3: + if ((fg.mOperator==1) || (fg.mOperator==2)) { + parenthese=true; + string.append('('); + } + fg.writeTree(string); + if (parenthese==true) + string.append(')'); + parenthese=false; + string.append('*'); + if ((fd.mOperator==1) || (fd.mOperator==2)) { + parenthese=true; + string.append('('); + } + fd.writeTree(string); + if (parenthese==true) + string.append(')'); + break; + case 4: + if ((fg.mOperator==1) || (fg.mOperator==2)) { + parenthese=true; + string.append('('); + } + fg.writeTree(string); + if (parenthese==true) + string.append(')'); + parenthese=false; + string.append('/'); + if ((fd.mOperator>0) && (fd.mOperator<5)) { + parenthese=true; + string.append('('); + } + fd.writeTree(string); + if (parenthese==true) + string.append(')'); + break; + case 5: + if ((fg.mOperator>0) && (fg.mOperator<5)) { + parenthese=true; + string.append('('); + } + fg.writeTree(string); + if (parenthese==true) + string.append(')'); + parenthese=false; + string.append('^'); + if ((fd.mOperator>0) && (fd.mOperator<5)) { + parenthese=true; + string.append('('); + } + fd.writeTree(string); + if (parenthese==true) + string.append(')'); + break; + case 6: + string.append("exp("); + fg.writeTree(string); + string.append(')'); + break; + case 7: + string.append("log("); + fg.writeTree(string); + string.append(')'); + break; + case 8: + string.append("ln("); + fg.writeTree(string); + string.append(')'); + break; + case 9: + string.append("�("); + fg.writeTree(string); + string.append(')'); + break; + case 10: + string.append("|"); + fg.writeTree(string); + string.append('|'); + break; + case 11: + string.append("sin("); + fg.writeTree(string); + string.append(')'); + break; + case 12: + string.append("cos("); + fg.writeTree(string); + string.append(')'); + break; + case 13: + string.append("tan("); + fg.writeTree(string); + string.append(')'); + break; + case 14: + string.append("asin("); + fg.writeTree(string); + string.append(')'); + break; + case 15: + string.append("acos("); + fg.writeTree(string); + string.append(')'); + break; + case 16: + string.append("atan("); + fg.writeTree(string); + string.append(')'); + break; + } + } + + //.................................................................................... calc_const + + private static double calc_const(StringBuffer chaine,int pos) { + int i=pos,j; + double temp=0; + int signe=1; + int longueur=chaine.length(); + + + if (chaine.charAt(i)=='-') { + signe=-1; + i++; + } + if (chaine.charAt(i)=='�') return signe*Math.PI; + + while (i47 && chaine.charAt(i)<58) { + temp=temp*10+(chaine.charAt(i)-48); + i++; + } + if (i47 && chaine.charAt(i)<58) { + temp=temp+(chaine.charAt(i)-48)*Math.exp(-j*2.30258509); + i++; + j++; + } + } + return (signe*temp); + } + + //.................................................................................... FindOperator + + private static void FindOperator(VariableInt oper,VariableInt esp,StringBuffer chaine,int pos) { + switch(chaine.charAt(pos)) { + case 'a': + switch(chaine.charAt(pos+1)) { + case 'b': + esp.mValue=3; + oper.mValue=10; + break; + case 'c': + esp.mValue=4; + oper.mValue=15; + break; + case 's': + esp.mValue=4; + oper.mValue=14; + break; + case 't': + esp.mValue=4; + oper.mValue=16; + break; + } + break; + case 'c': + if (chaine.charAt(pos+1)=='h') { + esp.mValue=2; + oper.mValue=18; + } + else if ((chaine.charAt(pos+1)=='o') && (chaine.charAt(pos+2)=='s')) { + if (chaine.charAt(pos+3)=='h') { + esp.mValue=4; + oper.mValue=18; + } + else { + esp.mValue=3; + oper.mValue=12; + } + } + break; + case 'e': + if ((chaine.charAt(pos+1)=='x') && (chaine.charAt(pos+2)=='p')) { + esp.mValue=3; + oper.mValue=6; + } + else oper.mValue=-10; + break; + case 'l': + if (chaine.charAt(pos+1)=='n') { + esp.mValue=2; + oper.mValue=7; + } + else if ((chaine.charAt(pos+1)=='o') && (chaine.charAt(pos+2)=='g')){ + esp.mValue=3; + oper.mValue=8; + } + else oper.mValue=-10; + break; + case 's': + if (chaine.charAt(pos+1)=='h') { + esp.mValue=2; + oper.mValue=17; + } + else if (chaine.charAt(pos+1)=='q') { + esp.mValue=4; + oper.mValue=9; + } + else { + if (chaine.charAt(pos+3)=='h') { + esp.mValue=4; + oper.mValue=17; + } + else { + esp.mValue=3; + oper.mValue=11; + } + } + break; + case 't': + if (chaine.charAt(pos+1)=='h') { + esp.mValue=2; + oper.mValue=19; + } + else if ((chaine.charAt(pos+1)=='a') && (chaine.charAt(pos+2)=='n')) { + if (chaine.charAt(pos+3)=='h') { + esp.mValue=4; + oper.mValue=19; + } + else { + esp.mValue=3; + oper.mValue=13; + } + } + else oper.mValue=-10; + break; + default: + oper.mValue=-10; + break; + } + } + + //.................................................................................... CopyPartialString + + private static StringBuffer CopyPartialString(StringBuffer chaine,int debut,int fin) { + StringBuffer chartemp; + int a=fin-debut+1; + chartemp=new StringBuffer(a+1); + + for(int i=0;i