Java中有eval()函数吗?

发布于 2024-08-28 23:08:44 字数 177 浏览 3 评论 0 原文

我有一个如下所示的字符串:

String str = "4*5";

现在我必须使用该字符串获得 20 的结果。

我知道在其他一些语言中,eval() 函数会执行此操作。 我怎样才能在Java中做到这一点?

I have a string like the following:

String str = "4*5";

Now I have to get the result of 20 by using the string.

I know in some other languages the eval() function will do this.
How can I do this in Java?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

宫墨修音 2024-09-04 23:08:45

,Java(或任何编译语言)中不能有通用的“eval”。除非您愿意编写一个 Java 编译器和一个要在 Java 程序内部执行的 JVM。

,您可以使用一些库来计算数字代数表达式,如上面的 - 请参阅此帖子进行讨论

No, you can not have a generic "eval" in Java (or any compiled language). Unless you're willing to write a Java compiler AND a JVM to be executed inside of your Java program.

Yes, you can have some library to evaluate numeric algebraic expressions like the one above - see this thread for discussion.

甜警司 2024-09-04 23:08:45

正如之前的答案,Java 中没有为此提供标准 API。

您可以将 groovy jar 文件添加到您的路径中,然后 groovy.util.Eval.me("4*5") 即可完成您的工作。

As previous answers, there is no standard API in Java for this.

You can add groovy jar files to your path and groovy.util.Eval.me("4*5") gets your job done.

浸婚纱 2024-09-04 23:08:45

解决问题的一个有趣方法是您自己编写一个 eval() 函数!
我已经为你做到了!

您只需在代码中输入 FunctionSolver.solveByX(function,value) 即可使用 FunctionSolver 库。 function 属性是一个字符串,表示要求解的函数,value 属性是自变量的值
你的函数(必须是x)。

如果要求解包含多个自变量的函数,可以使用 FunctionSolver.solve(function,values),其中 < em>values 属性是一个 HashMap(String ,Double) 其中包含所有独立属性(作为字符串)及其各自的值(作为双精度)。

另一条信息:我编写了一个简单版本的FunctionSolver,因此它仅支持数学方法 返回一个双精度值并接受一个或两个双精度值作为字段(只需使用 FunctionSolver.usableMathMethods() if你很好奇)(这些方法是:bs、sin、cos、tan、atan2、sqrt、log、log10、pow、exp、min、max、copySign、signum、IEEEremainder、acos、asin、atan、cbrt 、ceil、cosh、expm1、floor、hypot、log1p、nextAfter、nextDown、nextUp、random、rint、sinh、tanh、toDegrees、toRadians、ulp)。另外,该库支持以下运算符:* / + - ^(即使 java 通常不支持 ^ 运算符)。

最后一件事:在创建这个库时,我必须使用 reflections 来调用 数学方法。我认为这真的很酷,如果您有兴趣,看看这个

就这样,这是代码(以及):

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();
}
 }

A fun way to solve your problem could be coding an eval() function on your own!
I've done it for you!

You can use FunctionSolver library simply by typing FunctionSolver.solveByX(function,value) inside your code. The function attribute is a String which represents the function you want to solve, the value attribute is the value of the independent variable
of your function (which MUST be x).

If you want to solve a function which contains more than one independent variable, you can use FunctionSolver.solve(function,values) where the values attribute is an HashMap(String,Double) which contains all your independent attributes (as Strings) and their respective values (as Doubles).

Another piece of information: I've coded a simple version of FunctionSolver, so its supports only Math methods which return a double value and which accepts one or two double values as fields (just use FunctionSolver.usableMathMethods() if you're curious) (These methods are: bs, sin, cos, tan, atan2, sqrt, log, log10, pow, exp, min, max, copySign, signum, IEEEremainder, acos, asin, atan, cbrt, ceil, cosh, expm1, floor, hypot, log1p, nextAfter, nextDown, nextUp, random, rint, sinh, tanh, toDegrees, toRadians, ulp). Also, that library supports the following operators: * / + - ^ (even if java normally does not support the ^ operator).

One last thing: while creating this library I had to use reflections to call Math methods. I think it's really cool, just have a look at this if you are interested in!

That's all, here it is the code (and the library):

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();
}
 }
丿*梦醉红颜 2024-09-04 23:08:45

编写自己的库并不像您想象的那么难。这是调车场算法的链接,其中包含逐步的算法解释。尽管如此,您必须首先解析输入的标记。

还有另外 2 个问题也可以为您提供一些信息:
将字符串转换为数学表达式?
什么是解析 java 中数学表达式的好库?< /a>

Writing your own library is not that hard as u might thing. Here is link for Shunting-yard algorithm with step by step algorithm explenation. Although, you will have to parse the input for tokens first.

There are 2 other questions wich can give you some information too:
Turn a String into a Math Expression?
What's a good library for parsing mathematical expressions in java?

凉宸 2024-09-04 23:08:45

由于答案有很多,我在 eval() 方法之上添加了我的实现,并添加了一些附加功能,例如支持阶乘、计算复杂表达式等。

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();
    }
}

请随时查找更新的要点 此处。如果有什么问题也可以评论。谢谢。

As there are many answers, I'm adding my implementation on top of eval() method with some additional features like support for factorial, evaluating complex expressions 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();
    }
}

Please find the updated gist anytime here. Also comment if any issues are there. Thanks.

沉睡月亮 2024-09-04 23:08:45

这里有一些完美的答案。然而,对于重要的脚本,可能需要将代码保留在缓存中,或者出于调试目的,甚至需要动态自更新代码。

为此,有时它是 通过命令行与 Java 交互更简单或更稳健创建临时目录输出您的脚本 和任何资产,创建 jar。最后导入新代码

尽管您当然可以通过从 jar 中的某个函数返回结果来实现 eval,但它有点超出了大多数语言中正常 eval() 使用的范围。

尽管如此,我还是想提一下这个方法,因为它完全封装了 Java 在没有第三方工具的情况下可以做的所有事情,以防万一。这个方法允许我将 HTML 模板转换为对象并保存它们,从而避免了在运行时解析模板的需要。

There are some perfectly capable answers here. However for non-trivial script it may be desirable to retain the code in a cache, or for debugging purposes, or even to have dynamically self-updating code.

To that end, sometimes it's simpler or more robust to interact with Java via command line. Create a temporary directory, output your script and any assets, create the jar. Finally import your new code.

It's a bit beyond the scope of normal eval() use in most languages, though you could certainly implement eval by returning the result from some function in your jar.

Still, thought I'd mention this method as it does fully encapsulate everything Java can do without 3rd party tools, in case of desperation. This method allows me to turn HTML templates into objects and save them, avoiding the need to parse a template at runtime.

别把无礼当个性 2024-09-04 23:08:45
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

class Calculate {
    public static void main(String[] args) {
        String  strng = "8*-2*3*-1*10/2+6-2";
        String[] oparator = {"+","-","*","/"};
        List<String> op1 = new ArrayList<>();
        String[] x = strng.split("");

        int sayac=0;
        for (String i : x) {
            sayac ++;
            for (String c : oparator) {
                if (i.equals(c)) {

                   try {
                       int j = Integer.parseInt(strng.substring(0, sayac - 1));
                       op1.add(strng.substring(0, sayac - 1));
                       op1.add(c);
                       strng = strng.substring(sayac);
                       sayac = 0;
                   }catch (Exception e)
                   {
                       continue;
                   }
                }

            }
        }
        op1.add(strng);

        ListIterator<String> it = op1.listIterator();
        List<List> newlist = new ArrayList<>() ;

        while (it.hasNext()) {

            List<String> p= new ArrayList<>();
            p.add(String.valueOf(it.nextIndex()));
            p.add(it.next());
            newlist.add(p);

        }

        int sayac2=0;
        String oparatorvalue = "*";
        calculate(sayac2,newlist,oparatorvalue);
        String oparatorvalue2 = "/";
        calculate(sayac2,newlist,oparatorvalue2);
        String oparatorvalue3 = "+";
        calculate(sayac2,newlist,oparatorvalue3);
        String oparatorvalue4 = "-";
        calculate(sayac2,newlist,oparatorvalue4);
        System.out.println("Result:"+newlist.get(0).get(1));


    }


    private static void calculate(int sayac2, List<List> newlist, String oparatorvalue) {
        while (sayac2<4){
            try{
                for (List j : newlist) {
                    if (j.get(1) == oparatorvalue) {
                        Integer opindex = newlist.indexOf(j);
                        Object sayi1 = newlist.get(opindex - 1).get(1);
                        Object sayi2 = newlist.get(opindex + 1).get(1);
                        int sonuc=0;
                        if (oparatorvalue.equals("*")){

                         sonuc = Integer.parseInt(sayi1.toString()) * Integer.parseInt(sayi2.toString());
                        }
                        if (oparatorvalue.equals("/")){

                            sonuc = Integer.parseInt(sayi1.toString()) / Integer.parseInt(sayi2.toString());
                        }
                        if (oparatorvalue.equals("+")){

                            sonuc = Integer.parseInt(sayi1.toString()) + Integer.parseInt(sayi2.toString());
                        }
                        if (oparatorvalue.equals("-")){

                            sonuc = Integer.parseInt(sayi1.toString()) - Integer.parseInt(sayi2.toString());
                        }
                        newlist.remove(opindex - 1);
                        newlist.remove(opindex - 1);
                        newlist.remove(opindex - 1);
                        List<String> sonuclist = new ArrayList<>();
                        sonuclist.add(String.valueOf(opindex - 1));
                        sonuclist.add(String.valueOf(sonuc));
                        newlist.add(opindex - 1, sonuclist);
                    }}}
            catch (Exception e){
                continue;
            }
            sayac2++;}
    }

}
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

class Calculate {
    public static void main(String[] args) {
        String  strng = "8*-2*3*-1*10/2+6-2";
        String[] oparator = {"+","-","*","/"};
        List<String> op1 = new ArrayList<>();
        String[] x = strng.split("");

        int sayac=0;
        for (String i : x) {
            sayac ++;
            for (String c : oparator) {
                if (i.equals(c)) {

                   try {
                       int j = Integer.parseInt(strng.substring(0, sayac - 1));
                       op1.add(strng.substring(0, sayac - 1));
                       op1.add(c);
                       strng = strng.substring(sayac);
                       sayac = 0;
                   }catch (Exception e)
                   {
                       continue;
                   }
                }

            }
        }
        op1.add(strng);

        ListIterator<String> it = op1.listIterator();
        List<List> newlist = new ArrayList<>() ;

        while (it.hasNext()) {

            List<String> p= new ArrayList<>();
            p.add(String.valueOf(it.nextIndex()));
            p.add(it.next());
            newlist.add(p);

        }

        int sayac2=0;
        String oparatorvalue = "*";
        calculate(sayac2,newlist,oparatorvalue);
        String oparatorvalue2 = "/";
        calculate(sayac2,newlist,oparatorvalue2);
        String oparatorvalue3 = "+";
        calculate(sayac2,newlist,oparatorvalue3);
        String oparatorvalue4 = "-";
        calculate(sayac2,newlist,oparatorvalue4);
        System.out.println("Result:"+newlist.get(0).get(1));


    }


    private static void calculate(int sayac2, List<List> newlist, String oparatorvalue) {
        while (sayac2<4){
            try{
                for (List j : newlist) {
                    if (j.get(1) == oparatorvalue) {
                        Integer opindex = newlist.indexOf(j);
                        Object sayi1 = newlist.get(opindex - 1).get(1);
                        Object sayi2 = newlist.get(opindex + 1).get(1);
                        int sonuc=0;
                        if (oparatorvalue.equals("*")){

                         sonuc = Integer.parseInt(sayi1.toString()) * Integer.parseInt(sayi2.toString());
                        }
                        if (oparatorvalue.equals("/")){

                            sonuc = Integer.parseInt(sayi1.toString()) / Integer.parseInt(sayi2.toString());
                        }
                        if (oparatorvalue.equals("+")){

                            sonuc = Integer.parseInt(sayi1.toString()) + Integer.parseInt(sayi2.toString());
                        }
                        if (oparatorvalue.equals("-")){

                            sonuc = Integer.parseInt(sayi1.toString()) - Integer.parseInt(sayi2.toString());
                        }
                        newlist.remove(opindex - 1);
                        newlist.remove(opindex - 1);
                        newlist.remove(opindex - 1);
                        List<String> sonuclist = new ArrayList<>();
                        sonuclist.add(String.valueOf(opindex - 1));
                        sonuclist.add(String.valueOf(sonuc));
                        newlist.add(opindex - 1, sonuclist);
                    }}}
            catch (Exception e){
                continue;
            }
            sayac2++;}
    }

}
谜兔 2024-09-04 23:08:45

如果您不想导入繁重的脚本库,可以使用 SimpleExpressionEvaluator 直接插入您的代码

用法:

Expression.eval("1+2").asString(); // returns "3.0"
Expression.eval("1+2").asInt(); // returns 3
Expression.eval("2>3").asString(); // returns "false"
Expression.eval("2>3").asBoolean(); // returns false
Expression.eval("(3>2)||((2<4)&&(2>1))").asString(); // returns "true"

使用变量:

HashMap<String, Object> st = new HashMap<String, Object>();  
st.put("a",1);  
st.put("b",2);  
st.put("c",3);  
st.put("d",4);  
Expression.eval("a+b", st).asInt();  // or simply asString()
Expression.eval("a>b",st).asBoolean();  // or simply asString()
Expression.eval("(c>b)||((b<d)&&(b>a))",st).asBoolean();  // or simply asString()
Expression.eval("(c>2)||((2<d)&&(b>1))",st).asBoolean();  // or simply asString()

使用 ExpressionBuilder:

Expression.expressionBuilder().putSymbol("a",2).putSymbol("b",3).build("(b>a)").evaluate()

If you do not want to import heavy scripting library, you can use SimpleExpressionEvaluator directly into your code

Usage:

Expression.eval("1+2").asString(); // returns "3.0"
Expression.eval("1+2").asInt(); // returns 3
Expression.eval("2>3").asString(); // returns "false"
Expression.eval("2>3").asBoolean(); // returns false
Expression.eval("(3>2)||((2<4)&&(2>1))").asString(); // returns "true"

With variables:

HashMap<String, Object> st = new HashMap<String, Object>();  
st.put("a",1);  
st.put("b",2);  
st.put("c",3);  
st.put("d",4);  
Expression.eval("a+b", st).asInt();  // or simply asString()
Expression.eval("a>b",st).asBoolean();  // or simply asString()
Expression.eval("(c>b)||((b<d)&&(b>a))",st).asBoolean();  // or simply asString()
Expression.eval("(c>2)||((2<d)&&(b>1))",st).asBoolean();  // or simply asString()

Using ExpressionBuilder:

Expression.expressionBuilder().putSymbol("a",2).putSymbol("b",3).build("(b>a)").evaluate()
塔塔猫 2024-09-04 23:08:45

以下解决了该问题:

ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
String str = "4*5";
System.out.println(engine.eval(str));

The following resolved the issue:

ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
String str = "4*5";
System.out.println(engine.eval(str));
月亮是我掰弯的 2024-09-04 23:08:44

您可以使用 ScriptEngine< /a> 类并将其计算为 Javascript 字符串。

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

可能有更好的方法,但这个有效。

You can use the ScriptEngine class and evaluate it as a Javascript string.

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

There may be a better way, but this one works.

您的好友蓝忘机已上羡 2024-09-04 23:08:44

没有标准的 Java 类或方法可以满足您的要求。您的选项包括:

  • 选择并使用一些第三方表达式评估库。例如 JEL 或列出的六个库中的任何一个 此处

  • 使用 eval 方法将表达式包装在类的 Java 源代码中,将其发送到 Java 编译器,然后加载生成的编译类。

  • 使用一些可以从 Java 调用的脚本语言作为表达式求值器。可能性包括 Javascript1、BeanShell 等。可以通过 脚本 API

  • 从头开始编写您自己的表达式计算器。

第一种方法可能是最简单的。如果您从不受信任的用户那里获取要计算的表达式,则第二种和第三种方法会存在潜在的安全风险。 (想想代码注入。)


1 - Java SE 中的 Javascript 是一个移动目标。从 Java 6 开始,Mozilla 的 Rhino Javascript 实现版本与 Java SE 捆绑在一起。在 Java 8 中,它被 Nashorn 取代。在 Java 11 中,Nashorn 被弃用,并最终从核心代码库中删除。截至 2021 年,Rhino 和 Nashorn 都作为单独的(非 Oracle)产品进行维护,并且 Oracle 的 GraalVM 有自己的 Javascript 实现。

There is no standard Java class or method that will do what you want. Your options include:

  • Select and use some third-party expression evaluation library. For example JEL or any of the half dozen libraries listed here.

  • Wrap the expression in the Java source code for a class with an eval method, send that to the Java compiler, and then load the resulting compiled class.

  • Use some scripting language that can be called from Java as an expression evaluator. Possibilities include Javascript1, BeanShell, and so on. A JSR 223 compliant scripting language implementation can be called via the Scripting API.

  • Write your own expression evaluator from scratch.

The first approach is probably simplest. The second and third approaches are a potential security risk if you get the expression to be evaluated from an untrusted user. (Think code injection.)


1 - Javascript in Java SE is a moving target. From Java 6, a version of Mozilla's Rhino Javascript implementation was bundled with Java SE. The in Java 8, it was superseded by Nashorn. In Java 11, Nashorn was deprecated, and finally dropped from the core codebase. As of 2021, both Rhino and Nashorn are being maintained as separate (non-Oracle) products, and Oracle's GraalVM has its own Javascript implementation.

只为守护你 2024-09-04 23:08:44

在很少的实际用例中,能够将 String 作为 Java 代码片段进行计算是必要或可取的。也就是说,询问如何做到这一点实际上是一个 XY 问题:你实际上有不同的问题,可以用不同的方式解决。

首先问问自己,您想要计算的这个 String 从哪里来?是程序的另一部分生成的,还是用户提供的输入?

  • 我的程序的另一部分生成了它:因此,您希望程序的一部分决定要执行的操作类型,但不执行该操作,而第二部分则执行所选操作手术。不要生成然后评估字符串,而是使用策略,< a href="http://en.wikipedia.org/wiki/Command_pattern" rel="noreferrer">命令 或 Builder 设计模式,适合您的具体情况。

  • 这是用户输入:用户可以输入任何内容,包括在执行时可能导致程序行为不当、崩溃、暴露应保密信息的命令、损坏持久性信息(例如数据库的内容)以及其他类似的恶意行为。防止这种情况的唯一方法是自己解析String,检查它不是恶意的,然后对其进行评估。但是,您自己解析它是所请求的 eval 函数要做的大部分工作,因此您没有为自己节省任何东西。更糟糕的是,检查任意 Java 是否是恶意的不可能,因为检查这是停止问题

  • 它是用户输入,但允许评估的文本的语法和语义受到很大限制:没有通用工具可以轻松实现通用解析器和评估器,无论您拥有什么受限的语法和语义选择的。您需要做的是为您选择的语法和语义实现一个解析器和评估器。如果任务很简单,您可以编写一个简单的 递归下降 或有限状态机解析器手工。如果任务很困难,您可以使用compiler-compiler(例如ANTLR)来为您做一些工作。

  • 我只是想实现一个桌面计算器!:家庭作业,嗯?如果您可以使用提供的 eval 函数来实现输入表达式的求值,那么这就不是什么作业了,不是吗?你的程序将是三行长。您的导师可能希望您为简单的算术解析器/评估器编写代码。有一个众所周知的算法,shunting-yard,您可能会发现它很有用。

There are very few real use cases in which being able to evaluate a String as a fragment of Java code is necessary or desirable. That is, asking how to do this is really an XY problem: you actually have a different problem, which can be solved a different way.

First ask yourself, where did this String that you wish to evaluate come from? Did another part of your program generate it, or was it input provided by the user?

  • Another part of my program generated it: so, you want one part of your program to decide the kind of operation to perform, but not perform the operation, and a second part that performs the chosen operation. Instead of generating and then evaluating a String, use the Strategy, Command or Builder design pattern, as appropriate for your particular case.

  • It is user input: the user could input anything, including commands that, when executed, could cause your program to misbehave, crash, expose information that should be secret, damage persistent information (such as the content of a database), and other such nastiness. The only way to prevent that would be to parse the String yourself, check it was not malicious, and then evaluate it. But parsing it yourself is much of the work that the requested evalfunction would do, so you have saved yourself nothing. Worse still, checking that arbitrary Java was not malicious is impossible, because checking that is the halting problem.

  • It is user input, but the syntax and semantics of permitted text to evaluate is greatly restricted: No general purpose facility can easily implement a general purpose parser and evaluator for whatever restricted syntax and semantics you have chosen. What you need to do is implement a parser and evaluator for your chosen syntax and semantics. If the task is simple, you could write a simple recursive-descent or finite-state-machine parser by hand. If the task is difficult, you could use a compiler-compiler (such as ANTLR) to do some of the work for you.

  • I just want to implement a desktop calculator!: A homework assignment, eh? If you could implement the evaluation of the input expression using a provided eval function, it would not be much of a homework assignment, would it? Your program would be three lines long. Your instructor probably expects you to write the code for a simple arithmetic parser/evaluator. There is well known algorithm, shunting-yard, which you might find useful.

此刻的回忆 2024-09-04 23:08:44

使用 Java 9,我们可以访问 jshell,所以可以写这样的东西:

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("> ");
            }
        }
    }
}

示例运行:

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

稍微有点op,但这就是Java当前必须提供的

With Java 9, we get access to jshell, so one can write something like this:

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("> ");
            }
        }
    }
}

Sample run:

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

Slightly op, but that's what Java currently has to offer

夜清冷一曲。 2024-09-04 23:08:44

我建议您使用 Exp4j。很容易理解,从下面的示例代码中可以看出:

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();

I could advise you to use Exp4j. It is easy to understand as you can see from the following example code:

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();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文