Évaluation d'une expression mathématique donnée sous forme de chaîne [closed]


J'essaie d'écrire une routine Java pour évaluer des expressions mathématiques simples à partir de String valeurs comme:

  1. "5+3"
  2. "10-40"
  3. "10*3"

Je veux éviter beaucoup d'instructions if-then-else. Comment puis-je faire cela?

Author: Francesco Menzani, 2010-08-06

24 answers

Avec JDK1.6, vous pouvez utiliser le moteur Javascript intégré.

import javax.script.ScriptEngineManager;
import javax.script.ScriptEngine;
import javax.script.ScriptException;

public class Test {
  public static void main(String[] args) throws ScriptException {
    ScriptEngineManager mgr = new ScriptEngineManager();
    ScriptEngine engine = mgr.getEngineByName("JavaScript");
    String foo = "40+2";
    System.out.println(engine.eval(foo));
    } 
}
 325
Author: RealHowTo, 2017-04-07 15:04:05

J'ai écrit ce eval méthode pour les expressions arithmétiques pour répondre à cette question. Il fait l'addition, la soustraction, la multiplication, la division, l'exponentiation (en utilisant le symbole ^), et quelques fonctions de base comme sqrt. Il prend en charge le regroupement en utilisant (...), et il devient l'opérateur préséance et associativité règles correctes.

public static double eval(final String str) {
    return new Object() {
        int pos = -1, ch;

        void nextChar() {
            ch = (++pos < str.length()) ? str.charAt(pos) : -1;
        }

        boolean eat(int charToEat) {
            while (ch == ' ') nextChar();
            if (ch == charToEat) {
                nextChar();
                return true;
            }
            return false;
        }

        double parse() {
            nextChar();
            double x = parseExpression();
            if (pos < str.length()) throw new RuntimeException("Unexpected: " + (char)ch);
            return x;
        }

        // Grammar:
        // expression = term | expression `+` term | expression `-` term
        // term = factor | term `*` factor | term `/` factor
        // factor = `+` factor | `-` factor | `(` expression `)`
        //        | number | functionName factor | factor `^` factor

        double parseExpression() {
            double x = parseTerm();
            for (;;) {
                if      (eat('+')) x += parseTerm(); // addition
                else if (eat('-')) x -= parseTerm(); // subtraction
                else return x;
            }
        }

        double parseTerm() {
            double x = parseFactor();
            for (;;) {
                if      (eat('*')) x *= parseFactor(); // multiplication
                else if (eat('/')) x /= parseFactor(); // division
                else return x;
            }
        }

        double parseFactor() {
            if (eat('+')) return parseFactor(); // unary plus
            if (eat('-')) return -parseFactor(); // unary minus

            double x;
            int startPos = this.pos;
            if (eat('(')) { // parentheses
                x = parseExpression();
                eat(')');
            } else if ((ch >= '0' && ch <= '9') || ch == '.') { // numbers
                while ((ch >= '0' && ch <= '9') || ch == '.') nextChar();
                x = Double.parseDouble(str.substring(startPos, this.pos));
            } else if (ch >= 'a' && ch <= 'z') { // functions
                while (ch >= 'a' && ch <= 'z') nextChar();
                String func = str.substring(startPos, this.pos);
                x = parseFactor();
                if (func.equals("sqrt")) x = Math.sqrt(x);
                else if (func.equals("sin")) x = Math.sin(Math.toRadians(x));
                else if (func.equals("cos")) x = Math.cos(Math.toRadians(x));
                else if (func.equals("tan")) x = Math.tan(Math.toRadians(x));
                else throw new RuntimeException("Unknown function: " + func);
            } else {
                throw new RuntimeException("Unexpected: " + (char)ch);
            }

            if (eat('^')) x = Math.pow(x, parseFactor()); // exponentiation

            return x;
        }
    }.parse();
}

Exemple:

System.out.println(eval("((4 - 2^3 + 1) * -sqrt(3*3+4*4)) / 2"));

Sortie: 7.5 (qui est correcte)


, L'analyseur est un analyseur de descente récursif , utilise donc en interne des méthodes d'analyse distinctes pour chaque niveau de priorité d'opérateur dans sa grammaire. Je l'ai gardé court {[34] } donc il est facile à modifier, mais voici quelques idées avec lesquelles vous voudrez peut-être l'étendre:

  • Variables:

    Le bit de l'analyseur qui lit les noms des fonctions peut facilement être modifié pour gérer également des variables personnalisées, en recherchant des noms dans une table de variables transmise à la méthode eval, comme un Map<String,Double> variables.

  • Compilation et évaluation séparées:

    Et si, après avoir ajouté le support des variables, vous vouliez évaluer la même expression des millions de fois avec des variables modifiées, sans l'analyser à chaque fois? Il est possible de faire. Définissez d'abord une interface à utiliser pour évaluer l'expression précompilée:

    @FunctionalInterface
    interface Expression {
        double eval();
    }
    

    Changez maintenant toutes les méthodes qui renvoient doubles, donc à la place elles renvoient une instance de cette interface. La syntaxe lambda de Java 8 fonctionne excellent pour cela. Exemple d'une des méthodes modifiées:

    Expression parseExpression() {
        Expression x = parseTerm();
        for (;;) {
            if (eat('+')) { // addition
                Expression a = x, b = parseTerm();
                x = (() -> a.eval() + b.eval());
            } else if (eat('-')) { // subtraction
                Expression a = x, b = parseTerm();
                x = (() -> a.eval() - b.eval());
            } else {
                return x;
            }
        }
    }
    

    Qui construit un arbre récursif d'objets Expression représentant l'expression compilée (un arbre de syntaxe abstraite ). Ensuite, vous pouvez le compiler une fois et l'évaluer à plusieurs reprises avec différentes valeurs:

    public static void main(String[] args) {
        Map<String,Double> variables = new HashMap<>();
        Expression exp = parse("x^2 - x + 2", variables);
        for (double x = -20; x <= +20; x++) {
            variables.put("x", x);
            System.out.println(x + " => " + exp.eval());
        }
    }
    
  • Les Différents types de données:

    Au Lieu de double, vous pouvez modifier l'évaluateur d'utiliser quelque chose de plus puissant comme BigDecimal, ou une classe qui implémente des nombres complexes, ou nombres rationnels (fractions). Vous pouvez même utiliser Object, permettant un mélange de types de données dans les expressions, tout comme un vrai langage de programmation. :)


Tout le code de cette réponse a été publié dans le domaine public. Amuse-toi bien!

 171
Author: Boann, 2016-07-18 00:20:41

La bonne façon de résoudre ce problème est avec un lexer et a analyseur. Vous pouvez écrire des versions simples de ceux-ci vous-même, ou ces pages ont également des liens vers des lexers et des analyseurs Java.

Créer un analyseur de descente récursif est un très bon exercice d'apprentissage.

 27
Author: Greg Hewgill, 2010-08-06 10:15:17

VOICI une autre bibliothèque open source sur GitHub nommée EvalEx.

Contrairement au moteur JavaScript, cette bibliothèque se concentre uniquement sur l'évaluation des expressions mathématiques. De plus, la bibliothèque est extensible et prend en charge l'utilisation d'opérateurs booléens ainsi que des parenthèses.

 15
Author: Tanvir, 2013-09-04 00:41:27

Vous pouvez également essayer l'interpréteur BeanShell:

Interpreter interpreter = new Interpreter();
interpreter.eval("result = (7+21*6)/(32-27)");
System.out.println(interpreter.get("result"));
 12
Author: marciowerner, 2012-10-11 20:06:12

Vous pouvez facilement évaluer des expressions si votre application Java accède déjà à une base de données, sans utiliser d'autres fichiers JAR.

Certaines bases de données vous obligent à utiliser une table factice (par exemple, la table "double" d'Oracle) et d'autres vous permettront d'évaluer des expressions sans "sélectionner" dans une table.

Par exemple, dans Sql Server ou Sqlite

select (((12.10 +12.0))/ 233.0) amount

Et dans Oracle

select (((12.10 +12.0))/ 233.0) amount from dual;

L'avantage d'utiliser une base de données est que vous pouvez évaluer plusieurs expressions en même temps. Aussi la plupart des Les bases de données vous permettront d'utiliser des expressions très complexes et auront également un certain nombre de fonctions supplémentaires qui peuvent être appelées si nécessaire.

Cependant, les performances peuvent souffrir si de nombreuses expressions uniques doivent être évaluées individuellement, en particulier lorsque la base de données est située sur un serveur réseau.

Ce qui suit résout le problème de performance dans une certaine mesure, en utilisant une base de données Sqlite en mémoire.

Voici un exemple de travail complet en Java

Class. forName("org.sqlite.JDBC");
Connection conn = DriverManager.getConnection("jdbc:sqlite::memory:");
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery( "select (1+10)/20.0 amount");
rs.next();
System.out.println(rs.getBigDecimal(1));
stat.close();
conn.close();

Bien sûr que vous pourrait étendre le code ci-dessus pour gérer plusieurs calculs en même temps.

ResultSet rs = stat.executeQuery( "select (1+10)/20.0 amount, (1+100)/20.0 amount2");
 12
Author: DAB, 2016-12-16 16:44:37

Pour mon projet universitaire, je cherchais un analyseur / évaluateur supportant à la fois les formules de base et les équations plus compliquées (en particulier les opérateurs itérés). J'ai trouvé une très belle bibliothèque open source pour JAVA et. NET appelée mXparser. Je vais donner quelques exemples pour vous sentir sur la syntaxe, pour plus d'informations veuillez visiter le site web du projet (en particulier tutoriel section).

Http://mathparser.org/

Http://mathparser.org/mxparser-tutorial/

Http://mathparser.org/api/

Et quelques exemples

1 - Furmula simple

Expression e = new Expression("( 2 + 3/4 + sin(pi) )/2");
double v = e.calculate()

2 - Arguments et constantes définis par l'utilisateur

Argument x = new Argument("x = 10");
Constant a = new Constant("a = pi^2");
Expression e = new Expression("cos(a*x)", x, a);
double v = e.calculate()

3 - fonctions définies par l'Utilisateur

Function f = new Function("f(x, y, z) = sin(x) + cos(y*z)");
Expression e = new Expression("f(3,2,5)", f);
double v = e.calculate()

4 - Itération

Expression e = new Expression("sum( i, 1, 100, sin(i) )");
double v = e.calculate()

Meilleures salutations

 10
Author: Leroy Kegan, 2018-08-20 15:39:41

Cet article pointe vers 3 approches différentes, dont l'une est JEXL d'Apache et permet des scripts qui incluent des références à des objets java.

 7
Author: Brad Parks, 2012-07-02 20:32:43

Une autre façon est d'utiliser Spring Expression Language ou SpEL qui fait beaucoup plus avec l'évaluation des expressions mathématiques, donc peut-être un peu exagéré. Vous n'avez pas besoin d'utiliser Spring framework pour utiliser cette bibliothèque d'expressions car elle est autonome. Copier des exemples de la documentation de SpEL:

ExpressionParser parser = new SpelExpressionParser();
int two = parser.parseExpression("1 + 1").getValue(Integer.class); // 2 
double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class); //24.0

Lire des exemples plus concis de SpEL ici et les documents complets ici

 6
Author: Faheem Sohail, 2014-02-26 13:55:20

C'est une autre alternative intéressante https://github.com/Shy-Ta/expression-evaluator-demo

L'utilisation est très simple et fait le travail, par exemple:

  ExpressionsEvaluator evalExpr = ExpressionsFactory.create("2+3*4-6/2");  
  assertEquals(BigDecimal.valueOf(11), evalExpr.eval()); 
 6
Author: Scorpion, 2015-07-01 05:24:50

Je pense que de toute façon, cela impliquera beaucoup d'instructions conditionnelles. Mais pour des opérations simples comme dans vos exemples, vous pouvez le limiter à 4 instructions if avec quelque chose comme

String math = "1+4";

if (math.split("+").length == 2) {
    //do calculation
} else if (math.split("-").length == 2) {
    //do calculation
} ...

Cela devient beaucoup plus compliqué lorsque vous voulez gérer plusieurs opérations comme "4+5*6".

Si vous essayez de construire une calculatrice, je passerais chaque section du calcul séparément (chaque nombre ou opérateur) plutôt que comme un seul chaîne.

 5
Author: BruteForce, 2010-08-06 10:12:52

Il semble que JEP devrait faire le travail

 5
Author: Bozho, 2010-08-06 10:37:24

Si nous allons l'implémenter, nous pouvons utiliser l'algorithme ci-dessous: {

  1. Bien qu'il y ait encore des jetons à lire,

    1.1 Obtenez le jeton suivant. 1.2 Si le jeton est:

    1.2.1 Un nombre: poussez-le sur la pile de valeurs.

    1.2.2 Une variable: obtenir sa valeur, et pousser sur la pile de valeurs.

    1.2.3 Une parenthèse gauche: poussez-la sur la pile de l'opérateur.

    1.2.4 Une parenthèse droite:

     1 While the thing on top of the operator stack is not a 
       left parenthesis,
         1 Pop the operator from the operator stack.
         2 Pop the value stack twice, getting two operands.
         3 Apply the operator to the operands, in the correct order.
         4 Push the result onto the value stack.
     2 Pop the left parenthesis from the operator stack, and discard it.
    

    1.2.5 Un opérateur (appelez-le thisOp):

     1 While the operator stack is not empty, and the top thing on the
       operator stack has the same or greater precedence as thisOp,
       1 Pop the operator from the operator stack.
       2 Pop the value stack twice, getting two operands.
       3 Apply the operator to the operands, in the correct order.
       4 Push the result onto the value stack.
     2 Push thisOp onto the operator stack.
    
  2. Alors que la pile opérateur n'est pas vide, 1 Pop l'opérateur de la pile opérateur. 2 Pop la pile de valeurs deux fois, obtenir deux opérandes. 3 Appliquez l'opérateur aux opérandes, dans le bon ordre. 4 Poussez le résultat sur la pile de valeurs.

  3. À ce stade, la pile d'opérateurs doit être vide et la valeur la pile doit avoir qu'une seule valeur, qui est le résultat final.

 5
Author: Prashant Gautam, 2015-09-18 12:39:58

Vous pouvez jeter un œil au framework Symja:

ExprEvaluator util = new ExprEvaluator(); 
IExpr result = util.evaluate("10-40");
System.out.println(result.toString()); // -> "-30" 

Notez que des expressions définitivement plus complexes peuvent être évaluées:

// D(...) gives the derivative of the function Sin(x)*Cos(x)
IAST function = D(Times(Sin(x), Cos(x)), x);
IExpr result = util.evaluate(function);
// print: Cos(x)^2-Sin(x)^2
 3
Author: Laurent Magnin, 2015-10-29 13:40:05

Essayez l'exemple de code suivant en utilisant le moteur Javascript de JDK1.6 avec la gestion de l'injection de code.

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;

public class EvalUtil {
private static ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
public static void main(String[] args) {
    try {
        System.out.println((new EvalUtil()).eval("(((5+5)/2) > 5) || 5 >3 "));
        System.out.println((new EvalUtil()).eval("(((5+5)/2) > 5) || true"));
    } catch (Exception e) {
        e.printStackTrace();
    }
}
public Object eval(String input) throws Exception{
    try {
        if(input.matches(".*[a-zA-Z;~`#$_{}\\[\\]:\\\\;\"',\\.\\?]+.*")) {
            throw new Exception("Invalid expression : " + input );
        }
        return engine.eval(input);
    } catch (Exception e) {
        e.printStackTrace();
        throw e;
    }
 }
}
 2
Author: Bruce, 2016-09-24 08:11:22

Ceci complète en fait la réponse donnée par @Boann. Il a un léger bug qui fait que "-2 ^ 2" donne un résultat erroné de -4.0. Le problème pour cela est le point auquel l'exponentiation est évaluée dans his. Déplacez simplement l'exponentiation vers le bloc de parseTerm (), et tout ira bien. Jetez un oeil à ce qui suit, qui est La réponse de@Boann légèrement modifiée. La modification est dans les commentaires.

public static double eval(final String str) {
    return new Object() {
        int pos = -1, ch;

        void nextChar() {
            ch = (++pos < str.length()) ? str.charAt(pos) : -1;
        }

        boolean eat(int charToEat) {
            while (ch == ' ') nextChar();
            if (ch == charToEat) {
                nextChar();
                return true;
            }
            return false;
        }

        double parse() {
            nextChar();
            double x = parseExpression();
            if (pos < str.length()) throw new RuntimeException("Unexpected: " + (char)ch);
            return x;
        }

        // Grammar:
        // expression = term | expression `+` term | expression `-` term
        // term = factor | term `*` factor | term `/` factor
        // factor = `+` factor | `-` factor | `(` expression `)`
        //        | number | functionName factor | factor `^` factor

        double parseExpression() {
            double x = parseTerm();
            for (;;) {
                if      (eat('+')) x += parseTerm(); // addition
                else if (eat('-')) x -= parseTerm(); // subtraction
                else return x;
            }
        }

        double parseTerm() {
            double x = parseFactor();
            for (;;) {
                if      (eat('*')) x *= parseFactor(); // multiplication
                else if (eat('/')) x /= parseFactor(); // division
                else if (eat('^')) x = Math.pow(x, parseFactor()); //exponentiation -> Moved in to here. So the problem is fixed
                else return x;
            }
        }

        double parseFactor() {
            if (eat('+')) return parseFactor(); // unary plus
            if (eat('-')) return -parseFactor(); // unary minus

            double x;
            int startPos = this.pos;
            if (eat('(')) { // parentheses
                x = parseExpression();
                eat(')');
            } else if ((ch >= '0' && ch <= '9') || ch == '.') { // numbers
                while ((ch >= '0' && ch <= '9') || ch == '.') nextChar();
                x = Double.parseDouble(str.substring(startPos, this.pos));
            } else if (ch >= 'a' && ch <= 'z') { // functions
                while (ch >= 'a' && ch <= 'z') nextChar();
                String func = str.substring(startPos, this.pos);
                x = parseFactor();
                if (func.equals("sqrt")) x = Math.sqrt(x);
                else if (func.equals("sin")) x = Math.sin(Math.toRadians(x));
                else if (func.equals("cos")) x = Math.cos(Math.toRadians(x));
                else if (func.equals("tan")) x = Math.tan(Math.toRadians(x));
                else throw new RuntimeException("Unknown function: " + func);
            } else {
                throw new RuntimeException("Unexpected: " + (char)ch);
            }

            //if (eat('^')) x = Math.pow(x, parseFactor()); // exponentiation -> This is causing a bit of problem

            return x;
        }
    }.parse();
}
 2
Author: Romeo Sierra, 2017-05-23 11:47:18
package ExpressionCalculator.expressioncalculator;

import java.text.DecimalFormat;
import java.util.Scanner;

public class ExpressionCalculator {

private static String addSpaces(String exp){

    //Add space padding to operands.
    //https://regex101.com/r/sJ9gM7/73
    exp = exp.replaceAll("(?<=[0-9()])[\\/]", " / ");
    exp = exp.replaceAll("(?<=[0-9()])[\\^]", " ^ ");
    exp = exp.replaceAll("(?<=[0-9()])[\\*]", " * ");
    exp = exp.replaceAll("(?<=[0-9()])[+]", " + "); 
    exp = exp.replaceAll("(?<=[0-9()])[-]", " - ");

    //Keep replacing double spaces with single spaces until your string is properly formatted
    /*while(exp.indexOf("  ") != -1){
        exp = exp.replace("  ", " ");
     }*/
    exp = exp.replaceAll(" {2,}", " ");

       return exp;
}

public static Double evaluate(String expr){

    DecimalFormat df = new DecimalFormat("#.####");

    //Format the expression properly before performing operations
    String expression = addSpaces(expr);

    try {
        //We will evaluate using rule BDMAS, i.e. brackets, division, power, multiplication, addition and
        //subtraction will be processed in following order
        int indexClose = expression.indexOf(")");
        int indexOpen = -1;
        if (indexClose != -1) {
            String substring = expression.substring(0, indexClose);
            indexOpen = substring.lastIndexOf("(");
            substring = substring.substring(indexOpen + 1).trim();
            if(indexOpen != -1 && indexClose != -1) {
                Double result = evaluate(substring);
                expression = expression.substring(0, indexOpen).trim() + " " + result + " " + expression.substring(indexClose + 1).trim();
                return evaluate(expression.trim());
            }
        }

        String operation = "";
        if(expression.indexOf(" / ") != -1){
            operation = "/";
        }else if(expression.indexOf(" ^ ") != -1){
            operation = "^";
        } else if(expression.indexOf(" * ") != -1){
            operation = "*";
        } else if(expression.indexOf(" + ") != -1){
            operation = "+";
        } else if(expression.indexOf(" - ") != -1){ //Avoid negative numbers
            operation = "-";
        } else{
            return Double.parseDouble(expression);
        }

        int index = expression.indexOf(operation);
        if(index != -1){
            indexOpen = expression.lastIndexOf(" ", index - 2);
            indexOpen = (indexOpen == -1)?0:indexOpen;
            indexClose = expression.indexOf(" ", index + 2);
            indexClose = (indexClose == -1)?expression.length():indexClose;
            if(indexOpen != -1 && indexClose != -1) {
                Double lhs = Double.parseDouble(expression.substring(indexOpen, index));
                Double rhs = Double.parseDouble(expression.substring(index + 2, indexClose));
                Double result = null;
                switch (operation){
                    case "/":
                        //Prevent divide by 0 exception.
                        if(rhs == 0){
                            return null;
                        }
                        result = lhs / rhs;
                        break;
                    case "^":
                        result = Math.pow(lhs, rhs);
                        break;
                    case "*":
                        result = lhs * rhs;
                        break;
                    case "-":
                        result = lhs - rhs;
                        break;
                    case "+":
                        result = lhs + rhs;
                        break;
                    default:
                        break;
                }
                if(indexClose == expression.length()){
                    expression = expression.substring(0, indexOpen) + " " + result + " " + expression.substring(indexClose);
                }else{
                    expression = expression.substring(0, indexOpen) + " " + result + " " + expression.substring(indexClose + 1);
                }
                return Double.valueOf(df.format(evaluate(expression.trim())));
            }
        }
    }catch(Exception exp){
        exp.printStackTrace();
    }
    return 0.0;
}

public static void main(String args[]){

    Scanner scanner = new Scanner(System.in);
    System.out.print("Enter an Mathematical Expression to Evaluate: ");
    String input = scanner.nextLine();
    System.out.println(evaluate(input));
}

}

 2
Author: chejaras, 2018-02-15 08:18:43

Que diriez-vous de quelque chose comme ceci:

String st = "10+3";
int result;
for(int i=0;i<st.length();i++)
{
  if(st.charAt(i)=='+')
  {
    result=Integer.parseInt(st.substring(0, i))+Integer.parseInt(st.substring(i+1, st.length()));
    System.out.print(result);
  }         
}

Et faire la même chose pour tous les autres opérateurs mathématiques en conséquence ..

 1
Author: konxie, 2012-10-17 20:06:38

Il est possible de convertir n'importe quelle chaîne d'expression en notation infixe en notation postfixe en utilisant L'algorithme de triage de Djikstra. Le résultat de l'algorithme peut alors servir d'entrée à l' postfix algorithme avec renvoie le résultat de l'expression.

J'ai écrit un article à ce sujet ici, avec une implémentation en java

 1
Author: Emmanuel John, 2015-07-06 00:15:15

Il est trop tard pour répondre mais je suis tombé sur la même situation pour évaluer l'expression en java, cela pourrait aider quelqu'un

MVEL est-ce que l'évaluation d'exécution des expressions, nous pouvons écrire un code java dans String pour le faire évaluer dans ceci.

    String expressionStr = "x+y";
    Map<String, Object> vars = new HashMap<String, Object>();
    vars.put("x", 10);
    vars.put("y", 20);
    ExecutableStatement statement = (ExecutableStatement) MVEL.compileExpression(expressionStr);
    Object result = MVEL.executeExpression(statement, vars);
 1
Author: Saravana, 2015-10-19 12:37:25
import java.util.*;
StringTokenizer st;
int ans;

public class check { 
   String str="7 + 5";
   StringTokenizer st=new StringTokenizer(str);

   int v1=Integer.parseInt(st.nextToken());
   String op=st.nextToken();
   int v2=Integer.parseInt(st.nextToken());

   if(op.equals("+")) { ans= v1 + v2; }
   if(op.equals("-")) { ans= v1 - v2; }
   //.........
}
 1
Author: stone, 2016-03-29 16:21:01

Encore une autre option: https://github.com/stefanhaustein/expressionparser

J'ai implémenté cela pour avoir une option simple mais flexible pour permettre les deux:

Le TreeBuilder lié ci-dessus fait partie d'un CAS demo package qui fait la dérivation symbolique. Il y a aussi un DE BASE interprète exemple et j'ai commencé à construire un Tapuscrit interprète utiliser.

 1
Author: Stefan Haustein, 2016-04-17 01:00:30

Une bibliothèque externe comme RHINO ou NASHORN peut être utilisée pour exécuter javascript. Et javascript peut évaluer une formule simple sans parcer la chaîne. Aucun impact sur les performances si le code est bien écrit. Voici un exemple avec RHINO -

public class RhinoApp {
    private String simpleAdd = "(12+13+2-2)*2+(12+13+2-2)*2";

public void runJavaScript() {
    Context jsCx = Context.enter();
    Context.getCurrentContext().setOptimizationLevel(-1);
    ScriptableObject scope = jsCx.initStandardObjects();
    Object result = jsCx.evaluateString(scope, simpleAdd , "formula", 0, null);
    Context.exit();
    System.out.println(result);
}
 1
Author: Manish, 2017-10-20 03:50:53

Une classe Java qui peut évaluer des expressions mathématiques:

package test;

public class Calculator {

    public static Double calculate(String expression){
        if (expression == null || expression.length() == 0) {
            return null;
        }
        return calc(expression.replace(" ", ""));
    }
    public static Double calc(String expression) {

        if (expression.startsWith("(") && expression.endsWith(")")) {
            return calc(expression.substring(1, expression.length() - 1));
        }
        String[] containerArr = new String[]{expression};
        double leftVal = getNextOperand(containerArr);
        expression = containerArr[0];
        if (expression.length() == 0) {
            return leftVal;
        }
        char operator = expression.charAt(0);
        expression = expression.substring(1);

        while (operator == '*' || operator == '/') {
            containerArr[0] = expression;
            double rightVal = getNextOperand(containerArr);
            expression = containerArr[0];
            if (operator == '*') {
                leftVal = leftVal * rightVal;
            } else {
                leftVal = leftVal / rightVal;
            }
            if (expression.length() > 0) {
                operator = expression.charAt(0);
                expression = expression.substring(1);
            } else {
                return leftVal;
            }
        }
        if (operator == '+') {
            return leftVal + calc(expression);
        } else {
            return leftVal - calc(expression);
        }

    }

    private static double getNextOperand(String[] exp){
        double res;
        if (exp[0].startsWith("(")) {
            int open = 1;
            int i = 1;
            while (open != 0) {
                if (exp[0].charAt(i) == '(') {
                    open++;
                } else if (exp[0].charAt(i) == ')') {
                    open--;
                }
                i++;
            }
            res = calc(exp[0].substring(1, i - 1));
            exp[0] = exp[0].substring(i);
        } else {
            int i = 1;
            if (exp[0].charAt(0) == '-') {
                i++;
            }
            while (exp[0].length() > i && isNumber((int) exp[0].charAt(i))) {
                i++;
            }
            res = Double.parseDouble(exp[0].substring(0, i));
            exp[0] = exp[0].substring(i);
        }
        return res;
    }


    private static boolean isNumber(int c) {
        int zero = (int) '0';
        int nine = (int) '9';
        return (c >= zero && c <= nine) || c =='.';
    }

    public static void main(String[] args) {
        System.out.println(calculate("(((( -6 )))) * 9 * -1"));
        System.out.println(calc("(-5.2+-5*-5*((5/4+2)))"));

    }

}
 0
Author: Efi G, 2017-08-03 01:06:45