web-dev-qa-db-fra.com

Existe-t-il une fonction eval () en Java?

J'ai une chaîne comme celle-ci:

String str = "4*5";

Maintenant, je dois obtenir le résultat de 20 En utilisant la chaîne.

Je sais que dans d'autres langues, la fonction eval() le fera. Comment puis-je faire cela en Java?

137
karthi_ms

Vous pouvez utiliser la classe ScriptEngine et l'évaluer en tant que chaîne Javascript.

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
Object result = engine.eval("4*5");

Il y a peut-être un meilleur moyen, mais celui-ci fonctionne.

138
Jeff Storey

Il n'y a pas de classe ou méthode standard Java qui fera ce que vous voulez. Vos options incluent:

  • Sélectionnez et utilisez une bibliothèque d'évaluation d'expressions tierces. Par exemple, JEL ou n’importe laquelle de la demi-douzaine de bibliothèques répertoriées ici .

  • Enveloppez l'expression dans le code source Java d'une classe avec une méthode eval, envoyez-la au compilateur Java, puis chargez-la classe compilée résultante.

  • Utilisez un langage de script pouvant être appelé à partir de Java en tant qu’évaluateur d’expression. Les possibilités incluent Javascript, BeanShell, etc.).

  • Écrivez votre propre évaluateur d'expression à partir de zéro.

La première approche est probablement la plus simple. Les deuxième et troisième approches constituent un risque potentiel pour la sécurité si l'expression doit être évaluée par un utilisateur non approuvé. (Pensez l'injection de code.)

43
Stephen C

Il existe très peu de cas d'utilisation réels dans lesquels pouvoir évaluer un String en tant que fragment de Java est nécessaire ou souhaitable. C'est-à-dire qu'il est vraiment difficile de savoir comment procéder. un problème XY : vous avez en fait un problème différent, qui peut être résolu différemment.

Tout d'abord, demandez-vous d'où vient ce String que vous souhaitez évaluer? Est-ce qu'une autre partie de votre programme l'a généré ou est-ce que cela a été fourni par l'utilisateur?

  • Une autre partie de mon programme l'a généré : vous voulez donc qu'une partie de votre programme décide du type d'opération à exécuter, mais ne l'exécute pas, et une deuxième partie qui effectue l'opération choisie. Au lieu de générer puis d’évaluer un String, utilisez le modèle de conception Stratégie , Commande ou Constructeur , selon votre cas. Cas.

  • C'est une entrée utilisateur : l'utilisateur peut entrer n'importe quoi, y compris les commandes qui, une fois exécutées, pourraient causer votre programme se conduisent mal, plantent, exposent des informations qui devraient être secrètes, endommagent des informations persistantes (telles que le contenu d'une base de données), et d'autres telles actions malveillantes. Le seul moyen d'éviter cela serait d'analyser le String vous-même, de vérifier qu'il n'était pas malveillant et de l'évaluer ensuite. Mais l’analyse par vous-même est une grande partie du travail que la fonction demandée eval devrait effectuer. Vous n’avez donc rien épargné. Pire encore, vérifier que Java n’était pas malveillant est arbitraire impossible, car vérifier problème bloquant .

  • Il s'agit d'une entrée utilisateur, mais la syntaxe et la sémantique du texte autorisé à évaluer sont considérablement restreintes : Aucune installation à usage général ne peut facilement implémenter un analyseur et un évaluateur à usage général quelle que soit la syntaxe et la sémantique restreintes que vous avez choisies. Ce que vous devez faire, c'est implémenter un analyseur syntaxique et un évaluateur pour la syntaxe et la sémantique choisies. Si la tâche est simple, vous pouvez écrire à la main un analyseur simple récursif-descendant ou fini-machine à états finis. Si la tâche est difficile, vous pouvez utiliser un compilateur-compilateur (tel que ANTLR) pour effectuer une partie du travail à votre place.

  • Je veux juste mettre en place une calculatrice! : Un devoir, hein? Si vous pouviez implémenter l'évaluation de l'expression d'entrée en utilisant une fonction eval fournie, cela ne constituerait pas vraiment une tâche de devoir, n'est-ce pas? Votre programme aurait trois lignes. Votre instructeur s'attend probablement à ce que vous écriviez le code pour un analyseur/évaluateur arithmétique simple. Il existe un algorithme bien connu, shunt-yard , que vous pourriez trouver utile.

30
Raedwald

Je pourrais vous conseiller d'utiliser Exp4j . Il est facile à comprendre comme vous pouvez le voir dans l'exemple de code suivant:

Expression e = new ExpressionBuilder("3 * sin(y) - 2 / (x - 2)")
    .variables("x", "y")
    .build()
    .setVariable("x", 2.3)
    .setVariable("y", 3.14);
double result = e.evaluate();
12
chAlexey

Avec Java 9, nous avons accès à jshell , afin que l’on puisse écrire quelque chose comme ceci:

import jdk.jshell.JShell;
import Java.lang.StringBuilder;
import Java.io.BufferedReader;
import Java.io.InputStreamReader;
import Java.io.IOException;

public class Eval {
    public static void main(String[] args) throws IOException {
        try(JShell js = JShell.create(); BufferedReader br = new BufferedReader(new InputStreamReader(System.in))) {

            js.onSnippetEvent(snip -> {
                if (snip.status() == jdk.jshell.Snippet.Status.VALID) {
                    System.out.println("➜ " + snip.value());
                }
            });

            System.out.print("> ");
            for (String line = br.readLine(); line != null; line = br.readLine()) {
                js.eval(js.sourceCodeAnalysis().analyzeCompletion(line).source());
                System.out.print("> ");
            }
        }
    }
}

Échantillon échantillon:

> 1 + 2 / 4 * 3
➜ 1
> 32 * 121
➜ 3872
> 4 * 5
➜ 20
> 121 * 51
➜ 6171
>

Légèrement OP, mais c’est ce que Java a actuellement à offrir

8
smac89

En tant que réponses précédentes, il n'y a pas d'API standard dans Java pour cela.

Vous pouvez ajouter des fichiers jar groovy à votre chemin et groovy.util.Eval.me ("4 * 5") fait votre travail.

6
Adi

Non , vous ne pouvez pas avoir un "eval" générique dans Java (ou tout autre langage compilé). Sauf si vous Vous êtes prêt à écrire un compilateur Java ET une machine virtuelle Java à exécuter à l’intérieur de votre programme Java .

Oui , vous pouvez avoir une bibliothèque pour évaluer des expressions algébriques numériques comme celle ci-dessus - voir ce sujet pour en discuter .

5
DVK

Une façon amusante de résoudre votre problème pourrait être de coder vous-même une fonction eval ()! Je l'ai fait pour vous!

Vous pouvez utiliser la bibliothèque FunctionSolver simplement en tapant FunctionSolver.solveByX ( function, valeur) dans votre code. L'attribut fonction est une chaîne qui représente la fonction que vous souhaitez résoudre, l'attribut valeur est la valeur de la variable indépendante de votre fonction (qui DOIT être X).

Si vous souhaitez résoudre une fonction qui contient plusieurs variables indépendantes, vous pouvez utiliser FunctionSolver.solve ( function, values) = où l'attribut values est un HashMap (String, Double) qui contient tous vos attributs indépendants (sous forme de chaînes) et leurs valeurs respectives (sous forme de doublons).

Autre information: j'ai codé une version simple de FunctionSolver, donc elle ne prend en charge que méthodes mathématiques qui renvoie une valeur double et accepte une ou deux valeurs doubles comme champs (utilisez simplement FunctionSolver.usableMathMethods () si vous êtes curieux) (Ces méthodes sont: bs, sin, cos, bronzage, atan2, sqrt, log, log10, pow, exp, min, max, copySign, signum, IEEEremainder, acos, asin, atan, cbrt, ceil, cosh, expm1, étage, hypot, log1p, nextAown, nextUp, random, rint, sinh, tanh, tanh, toDegrees, toRadians, ulp) . En outre, cette bibliothèque prend en charge les opérateurs suivants: */+ - ^ (même si Java ne prend normalement pas en charge l'opérateur ^).

Une dernière chose: lors de la création de cette bibliothèque, je devais utiliser réflexions pour appeler méthodes mathématiques . Je pense que c'est vraiment cool, juste jetez un coup d'oeil à ça si cela vous intéresse!

C'est tout, ici c'est le code (et le bibliothèque ):

package core;

 import Java.lang.reflect.InvocationTargetException;
 import Java.lang.reflect.Method;
 import Java.util.ArrayList;
 import Java.util.Arrays;
 import Java.util.HashMap;

 public abstract class FunctionSolver {

public static double solveNumericExpression (String expression) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
    return solve(expression, new HashMap<>());
}

public static double solveByX (String function, double value) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

    HashMap<String, Double> values = new HashMap<>();
    values.put("x", value);
    return solveComplexFunction(function, function, values);
}

public static double solve (String function, HashMap<String,Double> values) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

    return solveComplexFunction(function, function, values);
}

private static double solveComplexFunction (String function, String motherFunction, HashMap<String, Double> values) throws NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {

    int position = 0;
    while(position < function.length()) {
        if (alphabetic.contains(""+function.charAt(position))) {
            if (position == 0 || !alphabetic.contains(""+function.charAt(position-1))) {
                int endIndex = -1;
                for (int j = position ; j < function.length()-1 ; j++) {
                    if (alphabetic.contains(""+function.charAt(j)) 
                            && !alphabetic.contains(""+function.charAt(j+1))) {
                        endIndex = j;
                        break;
                    }
                }
                if (endIndex == -1 & alphabetic.contains(""+function.charAt(function.length()-1))) {
                    endIndex = function.length()-1;
                }
                if (endIndex != -1) {
                    String alphabeticElement = function.substring(position, endIndex+1);
                    if (Arrays.asList(usableMathMethods()).contains(alphabeticElement)) {
                        //Start analyzing a Math function
                        int closeParenthesisIndex = -1;
                        int openedParenthesisquantity = 0;
                        int commaIndex = -1;
                        for (int j = endIndex+1 ; j < function.length() ; j++) {
                            if (function.substring(j,j+1).equals("(")) {
                                openedParenthesisquantity++;
                            }else if (function.substring(j,j+1).equals(")")) {
                                openedParenthesisquantity--;
                                if (openedParenthesisquantity == 0) {
                                    closeParenthesisIndex = j;
                                    break;
                                }
                            }else if (function.substring(j,j+1).equals(",") & openedParenthesisquantity == 0) {
                                if (commaIndex == -1) {
                                    commaIndex = j;
                                }else{
                                    throw new IllegalArgumentException("The argument of math function (which is "+alphabeticElement+") has too many commas");
                                }
                            }
                        }
                        if (closeParenthesisIndex == -1) {
                            throw new IllegalArgumentException("The argument of a Math function (which is "+alphabeticElement+") hasn't got the closing bracket )");
                        }   
                        String functionArgument = function.substring(endIndex+2,closeParenthesisIndex);
                        if (commaIndex != -1) {
                            double firstParameter = solveComplexFunction(functionArgument.substring(0,commaIndex),motherFunction,values);
                            double secondParameter = solveComplexFunction(functionArgument.substring(commaIndex+1),motherFunction,values);
                            Method mathMethod = Math.class.getDeclaredMethod(alphabeticElement, new Class<?>[] {double.class, double.class});
                            mathMethod.setAccessible(true);
                            String newKey = getNewKey(values);
                            values.put(newKey, (Double) mathMethod.invoke(null, firstParameter, secondParameter));
                            function = function.substring(0, position)+newKey
                                       +((closeParenthesisIndex == function.length()-1)?(""):(function.substring(closeParenthesisIndex+1)));
                        }else {
                            double firstParameter = solveComplexFunction(functionArgument, motherFunction, values);
                            Method mathMethod = Math.class.getDeclaredMethod(alphabeticElement, new Class<?>[] {double.class});
                            mathMethod.setAccessible(true);
                            String newKey = getNewKey(values);
                            values.put(newKey, (Double) mathMethod.invoke(null, firstParameter));
                            function = function.substring(0, position)+newKey
                                       +((closeParenthesisIndex == function.length()-1)?(""):(function.substring(closeParenthesisIndex+1)));
                        }   
                    }else if (!values.containsKey(alphabeticElement)) {
                        throw new IllegalArgumentException("Found a group of letters ("+alphabeticElement+") which is neither a variable nor a Math function: ");
                    }
                }
            }
        }
        position++;
    }
    return solveBracketsFunction(function,motherFunction,values);
}

private static double solveBracketsFunction (String function,String motherFunction,HashMap<String, Double> values) throws IllegalArgumentException{

    function = function.replace(" ", "");
    String openingBrackets = "([{";
    String closingBrackets = ")]}";
    int parenthesisIndex = 0;
    do {
        int position = 0;
        int openParenthesisBlockIndex = -1;
        String currentOpeningBracket = openingBrackets.charAt(parenthesisIndex)+"";
        String currentClosingBracket = closingBrackets.charAt(parenthesisIndex)+"";
        if (contOccouranceIn(currentOpeningBracket,function) != contOccouranceIn(currentClosingBracket,function)) {
            throw new IllegalArgumentException("Error: brackets are misused in the function "+function);
        }
        while (position < function.length()) {
            if (function.substring(position,position+1).equals(currentOpeningBracket)) {
                if (position != 0 && !operators.contains(function.substring(position-1,position))) {
                    throw new IllegalArgumentException("Error in function: there must be an operator following a "+currentClosingBracket+" breacket");
                }
                openParenthesisBlockIndex = position;
            }else if (function.substring(position,position+1).equals(currentClosingBracket)) {
                if (position != function.length()-1 && !operators.contains(function.substring(position+1,position+2))) {
                    throw new IllegalArgumentException("Error in function: there must be an operator before a "+currentClosingBracket+" breacket");
                }
                String newKey = getNewKey(values);
                values.put(newKey, solveBracketsFunction(function.substring(openParenthesisBlockIndex+1,position),motherFunction, values));
                function = function.substring(0,openParenthesisBlockIndex)+newKey
                           +((position == function.length()-1)?(""):(function.substring(position+1)));
                position = -1;
            }
            position++;
        }
        parenthesisIndex++;
    }while (parenthesisIndex < openingBrackets.length());
    return solveBasicFunction(function,motherFunction, values);
}

private static double solveBasicFunction (String function, String motherFunction, HashMap<String, Double> values) throws IllegalArgumentException{

    if (!firstContainsOnlySecond(function, alphanumeric+operators)) {
        throw new IllegalArgumentException("The function "+function+" is not a basic function");
    }
    if (function.contains("**") |
        function.contains("//") |
        function.contains("--") |
        function.contains("+*") |
        function.contains("+/") |
        function.contains("-*") |
        function.contains("-/")) {
        /*
         * ( -+ , +- , *- , *+ , /- , /+ )> Those values are admitted
         */
        throw new IllegalArgumentException("Operators are misused in the function");
    }
    function = function.replace(" ", "");
    int position;
    int operatorIndex = 0;
    String currentOperator;
    do {
        currentOperator = operators.substring(operatorIndex,operatorIndex+1);
        if (currentOperator.equals("*")) {
            currentOperator+="/";
            operatorIndex++;
        }else if (currentOperator.equals("+")) {
            currentOperator+="-";
            operatorIndex++;
        }
        operatorIndex++;
        position = 0;
        while (position < function.length()) {
            if ((position == 0 && !(""+function.charAt(position)).equals("-") && !(""+function.charAt(position)).equals("+") && operators.contains(""+function.charAt(position))) ||
                (position == function.length()-1 && operators.contains(""+function.charAt(position)))){
                throw new IllegalArgumentException("Operators are misused in the function");
            }
            if (currentOperator.contains(function.substring(position, position+1)) & position != 0) {
                int firstTermBeginIndex = position;
                while (firstTermBeginIndex > 0) {
                    if ((alphanumeric.contains(""+function.charAt(firstTermBeginIndex))) & (operators.contains(""+function.charAt(firstTermBeginIndex-1)))){
                        break;
                    }
                    firstTermBeginIndex--;
                }
                if (firstTermBeginIndex != 0 && (function.charAt(firstTermBeginIndex-1) == '-' | function.charAt(firstTermBeginIndex-1) == '+')) {
                    if (firstTermBeginIndex == 1) {
                        firstTermBeginIndex--;
                    }else if (operators.contains(""+(function.charAt(firstTermBeginIndex-2)))){
                        firstTermBeginIndex--;
                    }
                }
                String firstTerm = function.substring(firstTermBeginIndex,position);
                int secondTermLastIndex = position;
                while (secondTermLastIndex < function.length()-1) {
                    if ((alphanumeric.contains(""+function.charAt(secondTermLastIndex))) & (operators.contains(""+function.charAt(secondTermLastIndex+1)))) {
                        break;
                    }
                    secondTermLastIndex++;
                }
                String secondTerm = function.substring(position+1,secondTermLastIndex+1);
                double result;
                switch (function.substring(position,position+1)) {
                    case "*": result = solveSingleValue(firstTerm,values)*solveSingleValue(secondTerm,values); break;
                    case "/": result = solveSingleValue(firstTerm,values)/solveSingleValue(secondTerm,values); break;
                    case "+": result = solveSingleValue(firstTerm,values)+solveSingleValue(secondTerm,values); break;
                    case "-": result = solveSingleValue(firstTerm,values)-solveSingleValue(secondTerm,values); break;
                    case "^": result = Math.pow(solveSingleValue(firstTerm,values),solveSingleValue(secondTerm,values)); break;
                    default: throw new IllegalArgumentException("Unknown operator: "+currentOperator);
                }
                String newAttribute = getNewKey(values);
                values.put(newAttribute, result);
                function = function.substring(0,firstTermBeginIndex)+newAttribute+function.substring(secondTermLastIndex+1,function.length());
                deleteValueIfPossible(firstTerm, values, motherFunction);
                deleteValueIfPossible(secondTerm, values, motherFunction);
                position = -1;
            }
            position++;
        }
    }while (operatorIndex < operators.length());
    return solveSingleValue(function, values);
}

private static double solveSingleValue (String singleValue, HashMap<String, Double> values) throws IllegalArgumentException{

    if (isDouble(singleValue)) {
        return Double.parseDouble(singleValue);
    }else if (firstContainsOnlySecond(singleValue, alphabetic)){
        return getValueFromVariable(singleValue, values);
    }else if (firstContainsOnlySecond(singleValue, alphanumeric+"-+")) {
        String[] composition = splitByLettersAndNumbers(singleValue);
        if (composition.length != 2) {
            throw new IllegalArgumentException("Wrong expression: "+singleValue);
        }else {
            if (composition[0].equals("-")) {
                composition[0] = "-1";
            }else if (composition[1].equals("-")) {
                composition[1] = "-1";
            }else if (composition[0].equals("+")) {
                composition[0] = "+1";
            }else if (composition[1].equals("+")) {
                composition[1] = "+1";
            }
            if (isDouble(composition[0])) {
                return Double.parseDouble(composition[0])*getValueFromVariable(composition[1], values);
            }else if (isDouble(composition[1])){
                return Double.parseDouble(composition[1])*getValueFromVariable(composition[0], values);
            }else {
                throw new IllegalArgumentException("Wrong expression: "+singleValue);
            }
        }
    }else {
        throw new IllegalArgumentException("Wrong expression: "+singleValue);
    }
}

private static double getValueFromVariable (String variable, HashMap<String, Double> values) throws IllegalArgumentException{

    Double val = values.get(variable);
    if (val == null) {
        throw new IllegalArgumentException("Unknown variable: "+variable);
    }else {
        return val;
    }
}

/*
 * FunctionSolver help tools:
 * 
 */

private static final String alphabetic = "abcdefghilmnopqrstuvzwykxy";
private static final String numeric = "0123456789.";
private static final String alphanumeric = alphabetic+numeric;
private static final String operators = "^*/+-"; //--> Operators order in important!

private static boolean firstContainsOnlySecond(String firstString, String secondString) {

    for (int j = 0 ; j < firstString.length() ; j++) {
        if (!secondString.contains(firstString.substring(j, j+1))) {
            return false;
        }
    }
    return true;
}

private static String getNewKey (HashMap<String, Double> hashMap) {

    String alpha = "abcdefghilmnopqrstuvzyjkx";
    for (int j = 0 ; j < alpha.length() ; j++) {
        String k = alpha.substring(j,j+1);
        if (!hashMap.containsKey(k) & !Arrays.asList(usableMathMethods()).contains(k)) {
            return k;
        }
    }
    for (int j = 0 ; j < alpha.length() ; j++) {
        for (int i = 0 ; i < alpha.length() ; i++) {
            String k = alpha.substring(j,j+1)+alpha.substring(i,i+1);
            if (!hashMap.containsKey(k) & !Arrays.asList(usableMathMethods()).contains(k)) {
                return k;
            }
        }
    }
    throw new NullPointerException();
}

public static String[] usableMathMethods () {

    /*
     *  Only methods that:
     *  return a double type
     *  present one or two parameters (which are double type)
     */

    Method[] mathMethods = Math.class.getDeclaredMethods();
    ArrayList<String> usableMethodsNames = new ArrayList<>();
    for (Method method : mathMethods) {
        boolean usable = true;
        int argumentsCounter = 0;
        Class<?>[] methodParametersTypes = method.getParameterTypes();
        for (Class<?> parameter : methodParametersTypes) {
            if (!parameter.getSimpleName().equalsIgnoreCase("double")) {
                usable = false;
                break;
            }else {
                argumentsCounter++;
            }
        }
        if (!method.getReturnType().getSimpleName().toLowerCase().equals("double")) {
            usable = false;
        }
        if (usable & argumentsCounter<=2) {
            usableMethodsNames.add(method.getName());
        }
    }
    return usableMethodsNames.toArray(new String[usableMethodsNames.size()]);
}

private static boolean isDouble (String number) {
    try {
        Double.parseDouble(number);
        return true;
    }catch (Exception ex) {
        return false;
    }
}

private static String[] splitByLettersAndNumbers (String val) {
    if (!firstContainsOnlySecond(val, alphanumeric+"+-")) {
        throw new IllegalArgumentException("Wrong passed value: <<"+val+">>");
    }
    ArrayList<String> response = new ArrayList<>();
    String searchingFor;
    int lastIndex = 0;
    if (firstContainsOnlySecond(""+val.charAt(0), numeric+"+-")) {
        searchingFor = alphabetic;
    }else {
        searchingFor = numeric+"+-";
    }
    for (int j = 0 ; j < val.length() ; j++) {
        if (searchingFor.contains(val.charAt(j)+"")) {
            response.add(val.substring(lastIndex, j));
            lastIndex = j;
            if (searchingFor.equals(numeric+"+-")) {
                searchingFor = alphabetic;
            }else {
                searchingFor = numeric+"+-";
            }
        }
    }
    response.add(val.substring(lastIndex,val.length()));
    return response.toArray(new String[response.size()]);
}

private static void deleteValueIfPossible (String val, HashMap<String, Double> values, String function) {
    if (values.get(val) != null & function != null) {
        if (!function.contains(val)) {
            values.remove(val);
        }
    }
}

private static int contOccouranceIn (String howManyOfThatString, String inThatString) {
    return inThatString.length() - inThatString.replace(howManyOfThatString, "").length();
}
 }
4
Vinciuz

Écrire votre propre bibliothèque n’est pas si difficile que cela puisse paraître. Voici le lien pour algorithme de triage avec une explication détaillée de l’algorithme. Bien que, vous devrez d'abord analyser l'entrée pour les jetons.

Deux autres questions peuvent également vous donner des informations: transformer une chaîne en expression mathématique?Qu'est-ce qu'une bonne bibliothèque pour analyser des expressions mathématiques en Java?

3
Srneczek

Comme il y a beaucoup de réponses, j'ajoute mon implémentation en plus de la méthode eval() avec quelques fonctionnalités supplémentaires telles que la prise en charge factorielle, l'évaluation d'expressions complexes, etc.

package evaluation;

import Java.math.BigInteger;
import Java.util.EmptyStackException;
import Java.util.Scanner;
import Java.util.Stack;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class EvalPlus {
    private static Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) {
        System.out.println("This Evaluation is based on BODMAS rule\n");
        evaluate();
    }

    private static void evaluate() {
        StringBuilder finalStr = new StringBuilder();
        System.out.println("Enter an expression to evaluate:");
        String expr = scanner.nextLine(); 
        if(isProperExpression(expr)) {
            expr = replaceBefore(expr);
            char[] temp = expr.toCharArray();
            String operators = "(+-*/%)";
            for(int i = 0; i < temp.length; i++) {
                if((i == 0 && temp[i] != '*') || (i == temp.length-1 && temp[i] != '*' && temp[i] != '!')) {
                    finalStr.append(temp[i]);
                } else if((i > 0 && i < temp.length -1) || (i==temp.length-1 && temp[i] == '!')) {
                    if(temp[i] == '!') {
                        StringBuilder str = new StringBuilder();
                        for(int k = i-1; k >= 0; k--) {
                            if(Character.isDigit(temp[k])) {
                                str.insert(0, temp[k] );
                            } else {
                                break;
                            }
                        }
                        Long prev = Long.valueOf(str.toString());
                        BigInteger val = new BigInteger("1");
                        for(Long j = prev; j > 1; j--) {
                            val = val.multiply(BigInteger.valueOf(j));
                        }
                        finalStr.setLength(finalStr.length() - str.length());
                        finalStr.append("(" + val + ")");
                        if(temp.length > i+1) {
                            char next = temp[i+1];
                            if(operators.indexOf(next) == -1) { 
                                finalStr.append("*");
                            }
                        }
                    } else {
                        finalStr.append(temp[i]);
                    }
                }
            }
            expr = finalStr.toString();
            if(expr != null && !expr.isEmpty()) {
                ScriptEngineManager mgr = new ScriptEngineManager();
                ScriptEngine engine = mgr.getEngineByName("JavaScript");
                try {
                    System.out.println("Result: " + engine.eval(expr));
                    evaluate();
                } catch (ScriptException e) {
                    System.out.println(e.getMessage());
                }
            } else {
                System.out.println("Please give an expression");
                evaluate();
            }
        } else {
            System.out.println("Not a valid expression");
            evaluate();
        }
    }

    private static String replaceBefore(String expr) {
        expr = expr.replace("(", "*(");
        expr = expr.replace("+*", "+").replace("-*", "-").replace("**", "*").replace("/*", "/").replace("%*", "%");
        return expr;
    }

    private static boolean isProperExpression(String expr) {
        expr = expr.replaceAll("[^()]", "");
        char[] arr = expr.toCharArray();
        Stack<Character> stack = new Stack<Character>();
        int i =0;
        while(i < arr.length) {
            try {
                if(arr[i] == '(') {
                    stack.Push(arr[i]);
                } else {
                    stack.pop();
                }
            } catch (EmptyStackException e) {
                stack.Push(arr[i]);
            }
            i++;
        }
        return stack.isEmpty();
    }
}

S'il vous plaît trouver le Gist mis à jour à tout moment ici . Également commenter si des problèmes sont là. Merci.

1
abubakkar

Il n'y a rien qui puisse faire cela dans JavaSE; vous devez trouver des bibliothèques tierces ou écrire les vôtres.

0