Есть ли в Java функция eval()?
У меня есть строка, подобная следующей:
String str = "4*5";
Теперь я должен получить результат 20
используя строку.
Я знаю на некоторых других языках eval()
Функция сделает это. Как я могу сделать это на Java?
15 ответов
Вы можете использовать ScriptEngine
Класс и оцените его как строку Javascript.
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("js");
Object result = engine.eval("4*5");
Возможно, есть лучший способ, но этот работает.
Не существует стандартного Java-класса или метода, который будет делать то, что вы хотите. Ваши варианты включают в себя:
Выберите и используйте какую-нибудь стороннюю библиотеку для оценки выражений. Например, JEL или любая из полдюжины библиотек, перечисленных здесь.
Оберните выражение в исходный код Java для класса с
eval
метод, отправьте это компилятору Java, а затем загрузите полученный скомпилированный класс.Используйте некоторый язык сценариев, который может быть вызван из Java в качестве оценщика выражений. Возможности включают в себя Javascript, BeanShell и так далее.
Написать свой собственный оценщик выражений с нуля.
Первый подход, вероятно, самый простой. Второй и третий подходы представляют собой потенциальную угрозу безопасности, если вы получите выражение, которое будет оценено ненадежным пользователем. (Подумайте о внедрении кода.)
Существует очень мало реальных случаев использования, в которых можно оценить String
так как фрагмент кода Java необходим или желателен. То есть вопрос о том, как это сделать, действительно является проблемой XY: на самом деле у вас другая проблема, которую можно решить другим способом.
Сначала спросите себя, откуда это String
откуда вы хотите оценить? Была ли другая часть вашей программы сгенерирована или введена пользователем?
Его сгенерировала другая часть моей программы: так, вы хотите, чтобы одна часть вашей программы определяла тип выполняемой операции, но не выполнение операции, и вторая часть, которая выполняет выбранную операцию. Вместо генерации, а затем оценки
String
используйте шаблон проектирования " Стратегия", " Команда" или " Строитель", соответствующий вашему конкретному случаю.Это пользовательский ввод: пользователь может вводить все, что угодно, в том числе команды, которые при выполнении могут привести к неправильной работе вашей программы, аварийному завершению работы, раскрытию информации, которая должна быть секретной, повреждению постоянной информации (например, содержимого базы данных) и другим подобным гадость. Единственный способ предотвратить это - разобрать
String
самостоятельно, проверьте, не было ли это вредоносным, а затем оцените его. Но синтаксический анализ это большая часть работы, которую запрашивалeval
Функция будет делать, так что вы ничего не спасли. Хуже того, проверяя, что произвольноJava
не было злым, невозможно, потому что проверка - это проблема остановки.Это пользовательский ввод, но синтаксис и семантика разрешенного текста для оценки сильно ограничены: никакое средство общего назначения не может легко реализовать синтаксический анализатор общего назначения для любого ограниченного синтаксиса и семантики, которые вы выбрали. Что вам нужно сделать, это реализовать анализатор и оценщик для выбранного вами синтаксиса и семантики. Если задача проста, вы можете написать простой парсер рекурсивного спуска или конечного автомата вручную. Если задача сложная, вы можете использовать компилятор-компилятор (такой как ANTLR), чтобы выполнить часть работы за вас.
Я просто хочу реализовать настольный калькулятор!: Домашнее задание, а? Если бы вы могли реализовать оценку входного выражения, используя
eval
функции, это не будет большая часть домашнего задания, не так ли? Ваша программа будет длиной в три строки. Ваш инструктор, вероятно, ожидает от вас написания кода для простого арифметического анализатора / оценщика. Существует хорошо известный алгоритм, шунтирующий двор, который может оказаться полезным.
С 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 в настоящее время может предложить
Я мог бы посоветовать вам использовать 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();
Нет, вы не можете иметь общий "eval" в Java (или любой другой скомпилированный язык). Если вы не хотите писать компилятор Java и JVM для выполнения внутри вашей Java-программы.
Да, вы можете иметь некоторую библиотеку для оценки числовых алгебраических выражений, подобных приведенному выше - смотрите эту тему для обсуждения.
Как и в предыдущих ответах, в Java для этого нет стандартного API.
Вы можете добавить файлы groovy jar на свой путь и groovy.util.Eval.me("4*5") выполнит вашу работу.
Интересным способом решения вашей проблемы может быть кодирование функции eval() самостоятельно! Я сделал это для тебя!
Вы можете использовать библиотеку FunctionSolver, просто набрав FunctionSolver.solveByX (function,value) внутри своего кода. Атрибут function - это строка, представляющая функцию, которую вы хотите решить, а атрибут value - это значение независимой переменной вашей функции (которая ДОЛЖНА быть x).
Если вы хотите решить функцию, которая содержит более одной независимой переменной, вы можете использовать FunctionSolver.solve(функция,значения), где атрибут values - это HashMap(String,Double), который содержит все ваши независимые атрибуты (как строки) и их соответствующие значения (как Doubles).
Еще одна информация: я написал простую версию FunctionSolver, поэтому она поддерживает только методы Math, которые возвращают двойное значение и которые принимают одно или два двойных значения в качестве полей (просто используйте FunctionSolver.usableMathMethods(), если вам интересно) (Эти методы: 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 обычно не поддерживает оператор ^).
И последнее: при создании этой библиотеки мне пришлось использовать отражения для вызова математических методов. Я думаю, что это действительно круто, просто посмотрите на это, если вам интересно!
Вот и все, вот код (и библиотека):
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();
}
}
Написание вашей собственной библиотеки не так сложно, как вы думаете. Вот ссылка на алгоритм Маневрового двора с пошаговым описанием алгоритма. Хотя сначала вам придется проанализировать входные данные для токенов.
Есть еще 2 вопроса, которые также могут дать вам некоторую информацию: Превратить строку в математическое выражение? Что такое хорошая библиотека для разбора математических выражений в Java?
Поскольку есть много ответов, я добавляю свою реализацию поверх 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();
}
}
Пожалуйста, найдите обновленную суть в любое время здесь. Также прокомментируйте, если есть какие-либо проблемы. Благодарю.
Нет ничего, что будет делать это в JavaSE; вам придется искать сторонние библиотеки или писать свои собственные.
Если вы не хотите импортировать тяжелую библиотеку сценариев, вы можете использовать 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()
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++;}
}
}
Здесь есть несколько вполне подходящих ответов. Однако для нетривиального сценария может быть желательно сохранить код в кеше или для целей отладки, или даже иметь динамически самообновляемый код.
С этой целью иногда проще или надежнее взаимодействовать с Java через командную строку. Создайте временный каталог, выведите свой скрипт и любые ресурсы, создайте банку. Наконец, импортируйте ваш новый код.
Это немного выходит за рамки обычного eval()
использовать на большинстве языков, хотя вы, безусловно, можете реализовать eval, вернув результат какой-либо функции в вашем банке.
Тем не менее, я подумал, что упомянул бы этот метод, поскольку он полностью инкапсулирует все, что Java может делать без сторонних инструментов, в случае отчаяния. Этот метод позволяет мне превращать шаблоны HTML в объекты и сохранять их, избегая необходимости анализировать шаблон во время выполнения.
Следующее решило проблему:
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
String str = "4*5";
System.out.println(engine.eval(str));