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?
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.
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.
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.
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
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();
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.
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.
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();
}
}
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?
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.
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.
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++;}
}
}
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()
The following resolved the issue:
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
String str = "4*5";
System.out.println(engine.eval(str));
It's my second time asking here and straight to the point. I can't seem to find a solution and I know it's not impossible. I wrote a java program that can generate a set of combination of any length, when I stop the program I don't want to start from the beginning how can I pick up from where I stopped?
Thanks.
Example (for length 3):
If I start from aaa ==> 9zI and I stop the program here, I don't want to start from aaa all over but start from 9zI and continue to 999. I just want to continue from where I left off.
public class Main {
public static void main(String[] args) {
S_Permutation sp = new S_Permutation();
String text = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
FileClass.fileExist("new.txt", true);
System.out.println("");
sp.permutation(text, "", 7, "sha256.txt","Kaaaaaa");
}
}
=====================================================================
public class S_Permutation {
private List<String> permutation;
public S_Permutation() {
permutation = new ArrayList<>();
}
public boolean saveThis(String words, char a, int limit) {
int count = 0;
limit++;
for (char character : words.toCharArray()) {
if (count == limit) {
return false;
}
if (character == a) {
count++;
} else {
count = 0;
}
}
return count < limit;
}
private int counter = 0;
private boolean seen = false;
public void permutation(String str, String prefix, int lengthOfPermutationString, String filename, String startPoint) {
if (prefix.equalsIgnoreCase(startPoint))
{
seen = true;
}
if (counter == 0) {
if (startPoint.length() != lengthOfPermutationString) {
for (int i = startPoint.length(); i < lengthOfPermutationString; i++) {
startPoint += str.charAt(0);
}
}
counter = -45;
}
if (prefix.length() == lengthOfPermutationString) {
boolean savethis = true;
for (int i = 0; i < prefix.length(); i++) {
savethis = this.saveThis(prefix, prefix.charAt(i), 13);
if (!savethis) {
break;
}
}
if (savethis && seen) {
System.out.println(prefix);
//permutation.add(prefix);
}
} else {
for (int i = 0; i < str.length(); i++) {
if (permutation.size() == 1000) {
FileClass.WriteFile("new.txt", permutation);
permutation.clear();
}
permutation(str, prefix + str.charAt(i), lengthOfPermutationString, filename, startPoint);
}
FileClass.WriteFile("new.txt", permutation);
permutation.clear();
}
}
}
=========================================================================
public class FileClass {
public static boolean WriteFile(String filename, List<String> doc) {
try {
if (!filename.contains(".txt")) {
filename += ".txt";
}
RandomAccessFile raf = new RandomAccessFile(filename, "rw");
String writer = "";
writer = doc.stream().map((string) -> string + "\n").reduce(writer, String::concat);
raf.seek(raf.length());
raf.writeBytes(writer);
raf.close();
} catch (Exception e) {
System.out.println(e.getMessage());
System.out.println("Error");
new Scanner(System.in).nextLine();
return false;
}
return true;
}
static RandomAccessFile raf;
public static boolean fileExist(String filename, boolean delete){
File file = new File(filename);
if (file.exists() && delete)
{
return file.delete();
}
return file.exists();
}
public static void WriteFile(String filename, String text) {
try {
if (!filename.contains(".txt")) {
filename += ".txt";
}
raf = new RandomAccessFile(filename, "rw");
long length = raf.length();
raf.setLength(length + 1);
raf.seek(raf.length());
raf.writeBytes(text + "\n");
} catch (Exception e) {
}
}
private static void write(List<String> records, Writer writer) throws IOException {
for (String record : records) {
writer.write(record);
}
writer.flush();
writer.close();
}
public static void stringWriter(List<String> records, String filename) {
try {
File file = new File(filename);
FileWriter writer = new FileWriter(file, true);
write(records, writer);
} catch (Exception ex) {
System.out.println(ex.getMessage());
new Scanner(System.in).nextLine();
}
}
public static boolean CloseFile() {
try {
raf.close();
return true;
} catch (Exception e) {
return false;
}
}
}
In order to add a "Resume" mechanism, you need to make your program idempotent. One way to do it, is instead of saving the permutations - save to file the parameters that are sent to permutation on each iteration:
now each time that the program starts, it will check what were the last parameters that permutation was called with (the last line in the file), and start from there (when the program starts on the first time, nothing will be written in the file - so it will start from the beginning).
After that the recursion finished, we can call another method that will go over the lines of the file, and read only the permutations (ignoring the other parameters) and write them into a cleaner "final_result.txt" file.
Needless to say that this implementation is more costly (all the additional reads and write from disc) but that's the tradeoff for having it support "resume" operation.
To save/restore process in the middle of its work, you need something we can call a "state" and implement generating combinations in iterative way.
In my implementation the "state" is pos object (I assume set and k will not change on "resume").
My implementation of the problem would be following:
public class RepeatComb {
private int[] pos;
private String set;
public RepeatComb(String set, int k) {
this.set = set;
pos = new int[k];
}
public int[] getState() {return Arrays.copyOf(pos, pos.length);}
public void resume(int[] a) {pos = Arrays.copyOf(a,a.length);}
public boolean next() {
int i = pos.length-1;
for (int maxpos = set.length()-1; pos[i] >= maxpos; ) {
if (i==0) return false;
--i;
}
++pos[i];
while (++i < pos.length) pos[i]=0;
return true;
}
public String getCur() {
StringBuilder s = new StringBuilder(pos.length);
for (int i=0; i < pos.length; ++i)
s.append(set.charAt(pos[i]));
return s.toString();
}
public static void main(String[] args) {
int[] state;
String text = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
RepeatComb comb = new RepeatComb(text, 3);
int stop = 10; //break after 10
do {
if (stop-- == 0) break;
System.out.println(comb.getCur());
} while (comb.next());
//save state
state = comb.getState();
System.out.println("---------");
//resume (with the same args: text,3)
stop = 10; //break after 10
comb = new RepeatComb(text, 3);
comb.resume(state); // resume here
do {
if (stop-- == 0) break;
System.out.println(comb.getCur());
} while (comb.next());
}
}
Update: I've added functions for getting state and resuming from it
and example of use. state array can be saved in file, then restored.