Я пытаюсь написать Java-процедуру для вычисления простых математических выражений из значений String
, например:
-
"5+3"
-
"10-40"
-
"10*3"
Я хочу избежать множества операторов if-then-else. Как я могу это сделать?
Я пытаюсь написать Java-процедуру для вычисления простых математических выражений из значений String
, например:
"5+3"
"10-40"
"10*3"
Я хочу избежать множества операторов if-then-else. Как я могу это сделать?
С JDK1.6 вы можете использовать встроенный механизм Javascript.
import javax.script.ScriptEngineManager;
import javax.script.ScriptEngine;
import javax.script.ScriptException;
public class Test {
public static void main(String[] args) throws ScriptException {
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine engine = mgr.getEngineByName("JavaScript");
String foo = "40+2";
System.out.println(engine.eval(foo));
}
}
Я написал этот метод eval
для арифметических выражений, чтобы ответить на этот вопрос. Это добавление, вычитание, умножение, деление, возведение в степень (с использованием символа ^
) и несколько основных функций, таких как sqrt
. Он поддерживает группировку с помощью (
... )
и получает оператор приоритет и associativity правильные правила.
public static double eval(final String str) {
return new Object() {
int pos = -1, ch;
void nextChar() {
ch = (++pos < str.length()) ? str.charAt(pos) : -1;
}
boolean eat(int charToEat) {
while (ch == ' ') nextChar();
if (ch == charToEat) {
nextChar();
return true;
}
return false;
}
double parse() {
nextChar();
double x = parseExpression();
if (pos < str.length()) throw new RuntimeException("Unexpected: " + (char)ch);
return x;
}
// Grammar:
// expression = term | expression `+` term | expression `-` term
// term = factor | term `*` factor | term `/` factor
// factor = `+` factor | `-` factor | `(` expression `)`
// | number | functionName factor | factor `^` factor
double parseExpression() {
double x = parseTerm();
for (;;) {
if (eat('+')) x += parseTerm(); // addition
else if (eat('-')) x -= parseTerm(); // subtraction
else return x;
}
}
double parseTerm() {
double x = parseFactor();
for (;;) {
if (eat('*')) x *= parseFactor(); // multiplication
else if (eat('/')) x /= parseFactor(); // division
else return x;
}
}
double parseFactor() {
if (eat('+')) return parseFactor(); // unary plus
if (eat('-')) return -parseFactor(); // unary minus
double x;
int startPos = this.pos;
if (eat('(')) { // parentheses
x = parseExpression();
eat(')');
} else if ((ch >= '0' && ch <= '9') || ch == '.') { // numbers
while ((ch >= '0' && ch <= '9') || ch == '.') nextChar();
x = Double.parseDouble(str.substring(startPos, this.pos));
} else if (ch >= 'a' && ch <= 'z') { // functions
while (ch >= 'a' && ch <= 'z') nextChar();
String func = str.substring(startPos, this.pos);
x = parseFactor();
if (func.equals("sqrt")) x = Math.sqrt(x);
else if (func.equals("sin")) x = Math.sin(Math.toRadians(x));
else if (func.equals("cos")) x = Math.cos(Math.toRadians(x));
else if (func.equals("tan")) x = Math.tan(Math.toRadians(x));
else throw new RuntimeException("Unknown function: " + func);
} else {
throw new RuntimeException("Unexpected: " + (char)ch);
}
if (eat('^')) x = Math.pow(x, parseFactor()); // exponentiation
return x;
}
}.parse();
}
Пример:
System.out.println(eval("((4 - 2^3 + 1) * -sqrt(3*3+4*4)) / 2"));
Результат: 7.5 (что правильно)
Переменные:
Бит анализатора, который читает имена функций, может быть легко изменен для обработки собственных переменных, путем поиска имен в таблице переменных, переданных методу eval
, например Map<String,Double> variables
.
Отдельная компиляция и оценка:
Что делать, если, добавив поддержку переменных, вы хотели бы оценить одно и то же выражение миллионы раз с измененными переменными без разбора его каждый раз? Возможно. Сначала определите интерфейс, который будет использоваться для оценки прекомпилированного выражения:
@FunctionalInterface
interface Expression {
double eval();
}
Теперь измените все методы, возвращающие double
s, поэтому вместо этого они возвращают экземпляр этого интерфейса. Синтаксис Java 8 lambda отлично подходит для этого. Пример одного из измененных методов:
Expression parseExpression() {
Expression x = parseTerm();
for (;;) {
if (eat('+')) { // addition
Expression a = x, b = parseTerm();
x = (() -> a.eval() + b.eval());
} else if (eat('-')) { // subtraction
Expression a = x, b = parseTerm();
x = (() -> a.eval() - b.eval());
} else {
return x;
}
}
}
Это создает рекурсивное дерево Expression
объектов, представляющих скомпилированное выражение (абстрактное синтаксическое дерево). Затем вы можете скомпилировать его один раз и многократно оценивать его разными значениями:
public static void main(String[] args) {
Map<String,Double> variables = new HashMap<>();
Expression exp = parse("x^2 - x + 2", variables);
for (double x = -20; x <= +20; x++) {
variables.put("x", x);
System.out.println(x + " => " + exp.eval());
}
}
Различные типы данных:
Вместо double
вы можете изменить оценщика, чтобы использовать что-то более мощное, например BigDecimal
, или класс, который реализует комплексные числа, или рациональные числа (дроби). Вы даже можете использовать Object
, позволяя смешивать типы данных в выражениях, точно так же, как настоящий язык программирования.:)
Весь код в этом ответе опубликовал в общедоступном домене. Получайте удовольствие!
Правильный способ решить это с помощью lexer и parser. Вы можете сами писать простые версии, или эти страницы также содержат ссылки на Java-лексеры и парсеры.
Создание рекурсивного парсера спуска - действительно хорошее упражнение.
ЗДЕСЬ - еще одна библиотека с открытым исходным кодом на GitHub с именем EvalEx.
В отличие от механизма JavaScript эта библиотека ориентирована только на оценку математических выражений. Кроме того, библиотека расширяема и поддерживает использование логических операторов, а также круглых скобок.
Вы также можете попробовать BeanShell интерпретатор:
Interpreter interpreter = new Interpreter();
interpreter.eval("result = (7+21*6)/(32-27)");
System.out.println(interpreter.get("result"));
Вы можете легко оценивать выражения, если ваше приложение Java уже обращается к базе данных без использования каких-либо других JAR.
В некоторых базах данных вы должны использовать фиктивную таблицу (например, таблицу "dual" Oracle), а другие позволят вам оценивать выражения без "выбора" из любой таблицы.
Например, в Sql Server или Sqlite
select (((12.10 +12.0))/ 233.0) amount
и в Oracle
select (((12.10 +12.0))/ 233.0) amount from dual;
Преимущество использования БД состоит в том, что вы можете одновременно оценить множество выражений. Также большинство БД позволят вам использовать очень сложные выражения и также будут иметь ряд дополнительных функций, которые можно назвать необходимыми.
Однако производительность может пострадать, если несколько отдельных выражений нужно оценивать индивидуально, особенно когда БД находится на сетевом сервере.
Ниже перечислены проблемы производительности в некоторой степени, используя базу данных Sqlite в памяти.
Здесь полный рабочий пример в Java
Class. forName("org.sqlite.JDBC");
Connection conn = DriverManager.getConnection("jdbc:sqlite::memory:");
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery( "select (1+10)/20.0 amount");
rs.next();
System.out.println(rs.getBigDecimal(1));
stat.close();
conn.close();
Конечно, вы могли бы расширить вышеуказанный код для одновременного обработки нескольких вычислений.
ResultSet rs = stat.executeQuery( "select (1+10)/20.0 amount, (1+100)/20.0 amount2");
Для моего университетского проекта я искал парсера/оценщика, поддерживающего как основные формулы, так и более сложные уравнения (особенно повторяющиеся операторы). Я нашел очень хорошую библиотеку с открытым исходным кодом для JAVA и.NET под названием mXparser. Я приведу несколько примеров, чтобы немного посидеть в синтаксисе, для получения дальнейших инструкций посетите веб-сайт проекта (особенно раздел "Учебник").
http://mathparser.org/mxparser-tutorial/
И несколько примеров
1 - Простая механика
Expression e = new Expression("( 2 + 3/4 + sin(pi) )/2");
double v = e.calculate()
2 - Пользовательские аргументы и константы
Argument x = new Argument("x = 10");
Constant a = new Constant("a = pi^2");
Expression e = new Expression("cos(a*x)", x, a);
double v = e.calculate()
3 - Пользовательские функции
Function f = new Function("f(x, y, z) = sin(x) + cos(y*z)");
Expression e = new Expression("f(3,2,5)", f);
double v = e.calculate()
4 - Итерация
Expression e = new Expression("sum( i, 1, 100, sin(i) )");
double v = e.calculate()
С наилучшими пожеланиями
Эта статья указывает на 3 разных подхода, один из которых JEXL из Apache и позволяет создавать сценарии, содержащие ссылки на объекты Java.
Другим способом является использование выражения Spring Expression Language или SpEL, который делает намного больше, наряду с оценкой математических выражений, поэтому может немного переборщить. Вам не обязательно использовать фреймворк Spring, чтобы использовать эту библиотеку выражений, поскольку она является автономной. Копирование примеров из документации Spel:
ExpressionParser parser = new SpelExpressionParser();
int two = parser.parseExpression("1 + 1").getValue(Integer.class); // 2
double twentyFour = parser.parseExpression("2.0 * 3e0 * 4").getValue(Double.class); //24.0
Прочтите более сжатые примеры SpEL здесь и полные документы здесь
Это еще одна интересная альтернатива https://github.com/Shy-Ta/expression-evaluator-demo
Использование очень простое и выполняет задание, например:
ExpressionsEvaluator evalExpr = ExpressionsFactory.create("2+3*4-6/2");
assertEquals(BigDecimal.valueOf(11), evalExpr.eval());
Я думаю, что когда-нибудь вы это сделаете, это будет связано с множеством условных утверждений. Но для одиночных операций, например, в ваших примерах, вы можете ограничить это до 4 операторов с чем-то вроде
String math = "1+4";
if (math.split("+").length == 2) {
//do calculation
} else if (math.split("-").length == 2) {
//do calculation
} ...
Это становится намного сложнее, если вы хотите иметь дело с несколькими операциями типа "4 + 5 * 6".
Если вы пытаетесь построить калькулятор, я бы опрокидывал каждую секцию вычисления отдельно (каждый номер или оператор), а не как одну строку.
Кажется, JEP должен выполнить задание
если мы собираемся его реализовать, тогда мы сможем использовать приведенный ниже алгоритм: -
Пока есть еще токены для чтения,
1.1. Получите следующий токен. 1.2 Если токен:
1.2.1 Число: нажмите на стек значений.
1.2.2 Переменная: получить ее значение и нажать на стек значений.
1.2.3 Левая скобка: надавите на стек оператора.
1.2.4 Прямая скобка:
1 While the thing on top of the operator stack is not a
left parenthesis,
1 Pop the operator from the operator stack.
2 Pop the value stack twice, getting two operands.
3 Apply the operator to the operands, in the correct order.
4 Push the result onto the value stack.
2 Pop the left parenthesis from the operator stack, and discard it.
1.2.5 Оператор (назовите его thisOp):
1 While the operator stack is not empty, and the top thing on the
operator stack has the same or greater precedence as thisOp,
1 Pop the operator from the operator stack.
2 Pop the value stack twice, getting two operands.
3 Apply the operator to the operands, in the correct order.
4 Push the result onto the value stack.
2 Push thisOp onto the operator stack.
Пока стек оператора не пуст, 1 Выполните посылку оператора из стека оператора. 2 Выполните дважды стек значений, получив два операнда. 3 Примените оператор к операндам в правильном порядке. 4 Нажмите результат на стек значений.
В этот момент стек оператора должен быть пустым, а значение стек должен иметь только одно значение, что является конечным результатом.
Вы можете взглянуть на инфраструктуру Symja:
ExprEvaluator util = new ExprEvaluator();
IExpr result = util.evaluate("10-40");
System.out.println(result.toString()); // -> "-30"
Обратите внимание, что можно определить более сложные выражения:
// D(...) gives the derivative of the function Sin(x)*Cos(x)
IAST function = D(Times(Sin(x), Cos(x)), x);
IExpr result = util.evaluate(function);
// print: Cos(x)^2-Sin(x)^2
Это фактически дополняет ответ, данный @Boann. У этого есть небольшая ошибка, которая вызывает "-2 ^ 2", чтобы дать ошибочный результат -4.0. Проблема для этого - точка, в которой в его оценке оценивается степень возведения в степень. Просто переместите экспоненцию в блок parseTerm(), и все будет хорошо. Посмотрите ниже, что @Boann answer слегка изменено. Модификация в комментариях.
public static double eval(final String str) {
return new Object() {
int pos = -1, ch;
void nextChar() {
ch = (++pos < str.length()) ? str.charAt(pos) : -1;
}
boolean eat(int charToEat) {
while (ch == ' ') nextChar();
if (ch == charToEat) {
nextChar();
return true;
}
return false;
}
double parse() {
nextChar();
double x = parseExpression();
if (pos < str.length()) throw new RuntimeException("Unexpected: " + (char)ch);
return x;
}
// Grammar:
// expression = term | expression `+` term | expression `-` term
// term = factor | term `*` factor | term `/` factor
// factor = `+` factor | `-` factor | `(` expression `)`
// | number | functionName factor | factor `^` factor
double parseExpression() {
double x = parseTerm();
for (;;) {
if (eat('+')) x += parseTerm(); // addition
else if (eat('-')) x -= parseTerm(); // subtraction
else return x;
}
}
double parseTerm() {
double x = parseFactor();
for (;;) {
if (eat('*')) x *= parseFactor(); // multiplication
else if (eat('/')) x /= parseFactor(); // division
else if (eat('^')) x = Math.pow(x, parseFactor()); //exponentiation -> Moved in to here. So the problem is fixed
else return x;
}
}
double parseFactor() {
if (eat('+')) return parseFactor(); // unary plus
if (eat('-')) return -parseFactor(); // unary minus
double x;
int startPos = this.pos;
if (eat('(')) { // parentheses
x = parseExpression();
eat(')');
} else if ((ch >= '0' && ch <= '9') || ch == '.') { // numbers
while ((ch >= '0' && ch <= '9') || ch == '.') nextChar();
x = Double.parseDouble(str.substring(startPos, this.pos));
} else if (ch >= 'a' && ch <= 'z') { // functions
while (ch >= 'a' && ch <= 'z') nextChar();
String func = str.substring(startPos, this.pos);
x = parseFactor();
if (func.equals("sqrt")) x = Math.sqrt(x);
else if (func.equals("sin")) x = Math.sin(Math.toRadians(x));
else if (func.equals("cos")) x = Math.cos(Math.toRadians(x));
else if (func.equals("tan")) x = Math.tan(Math.toRadians(x));
else throw new RuntimeException("Unknown function: " + func);
} else {
throw new RuntimeException("Unexpected: " + (char)ch);
}
//if (eat('^')) x = Math.pow(x, parseFactor()); // exponentiation -> This is causing a bit of problem
return x;
}
}.parse();
}
package ExpressionCalculator.expressioncalculator;
import java.text.DecimalFormat;
import java.util.Scanner;
public class ExpressionCalculator {
private static String addSpaces(String exp){
//Add space padding to operands.
//https://regex101.com/r/sJ9gM7/73
exp = exp.replaceAll("(?<=[0-9()])[\\/]", " / ");
exp = exp.replaceAll("(?<=[0-9()])[\\^]", " ^ ");
exp = exp.replaceAll("(?<=[0-9()])[\\*]", " * ");
exp = exp.replaceAll("(?<=[0-9()])[+]", " + ");
exp = exp.replaceAll("(?<=[0-9()])[-]", " - ");
//Keep replacing double spaces with single spaces until your string is properly formatted
/*while(exp.indexOf(" ") != -1){
exp = exp.replace(" ", " ");
}*/
exp = exp.replaceAll(" {2,}", " ");
return exp;
}
public static Double evaluate(String expr){
DecimalFormat df = new DecimalFormat("#.####");
//Format the expression properly before performing operations
String expression = addSpaces(expr);
try {
//We will evaluate using rule BDMAS, i.e. brackets, division, power, multiplication, addition and
//subtraction will be processed in following order
int indexClose = expression.indexOf(")");
int indexOpen = -1;
if (indexClose != -1) {
String substring = expression.substring(0, indexClose);
indexOpen = substring.lastIndexOf("(");
substring = substring.substring(indexOpen + 1).trim();
if(indexOpen != -1 && indexClose != -1) {
Double result = evaluate(substring);
expression = expression.substring(0, indexOpen).trim() + " " + result + " " + expression.substring(indexClose + 1).trim();
return evaluate(expression.trim());
}
}
String operation = "";
if(expression.indexOf(" / ") != -1){
operation = "/";
}else if(expression.indexOf(" ^ ") != -1){
operation = "^";
} else if(expression.indexOf(" * ") != -1){
operation = "*";
} else if(expression.indexOf(" + ") != -1){
operation = "+";
} else if(expression.indexOf(" - ") != -1){ //Avoid negative numbers
operation = "-";
} else{
return Double.parseDouble(expression);
}
int index = expression.indexOf(operation);
if(index != -1){
indexOpen = expression.lastIndexOf(" ", index - 2);
indexOpen = (indexOpen == -1)?0:indexOpen;
indexClose = expression.indexOf(" ", index + 2);
indexClose = (indexClose == -1)?expression.length():indexClose;
if(indexOpen != -1 && indexClose != -1) {
Double lhs = Double.parseDouble(expression.substring(indexOpen, index));
Double rhs = Double.parseDouble(expression.substring(index + 2, indexClose));
Double result = null;
switch (operation){
case "/":
//Prevent divide by 0 exception.
if(rhs == 0){
return null;
}
result = lhs / rhs;
break;
case "^":
result = Math.pow(lhs, rhs);
break;
case "*":
result = lhs * rhs;
break;
case "-":
result = lhs - rhs;
break;
case "+":
result = lhs + rhs;
break;
default:
break;
}
if(indexClose == expression.length()){
expression = expression.substring(0, indexOpen) + " " + result + " " + expression.substring(indexClose);
}else{
expression = expression.substring(0, indexOpen) + " " + result + " " + expression.substring(indexClose + 1);
}
return Double.valueOf(df.format(evaluate(expression.trim())));
}
}
}catch(Exception exp){
exp.printStackTrace();
}
return 0.0;
}
public static void main(String args[]){
Scanner scanner = new Scanner(System.in);
System.out.print("Enter an Mathematical Expression to Evaluate: ");
String input = scanner.nextLine();
System.out.println(evaluate(input));
}
}
Попробуйте использовать следующий пример кода, используя JDK1.6 Javascript engine с обработкой впрыска кода.
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
public class EvalUtil {
private static ScriptEngine engine = new ScriptEngineManager().getEngineByName("JavaScript");
public static void main(String[] args) {
try {
System.out.println((new EvalUtil()).eval("(((5+5)/2) > 5) || 5 >3 "));
System.out.println((new EvalUtil()).eval("(((5+5)/2) > 5) || true"));
} catch (Exception e) {
e.printStackTrace();
}
}
public Object eval(String input) throws Exception{
try {
if(input.matches(".*[a-zA-Z;~`#$_{}\\[\\]:\\\\;\"',\\.\\?]+.*")) {
throw new Exception("Invalid expression : " + input );
}
return engine.eval(input);
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
}
import java.util.*;
StringTokenizer st;
int ans;
public class check {
String str="7 + 5";
StringTokenizer st=new StringTokenizer(str);
int v1=Integer.parseInt(st.nextToken());
String op=st.nextToken();
int v2=Integer.parseInt(st.nextToken());
if(op.equals("+")) { ans= v1 + v2; }
if(op.equals("-")) { ans= v1 - v2; }
//.........
}
Как насчет чего-то вроде этого:
String st = "10+3";
int result;
for(int i=0;i<st.length();i++)
{
if(st.charAt(i)=='+')
{
result=Integer.parseInt(st.substring(0, i))+Integer.parseInt(st.substring(i+1, st.length()));
System.out.print(result);
}
}
и делать то же самое для каждого другого математического оператора соответственно.
Можно преобразовать любую строку выражения в нотацию infix в постфиксную нотацию, используя алгоритм shink-yard Djikstra. Результат алгоритма затем может служить входом в постфиксный алгоритм с возвратом результата выражения.
Я написал статью об этом здесь, с реализацией в java
Слишком поздно ответить, но я столкнулся с той же ситуацией, чтобы оценить выражение в java, это может помочь кому-то
MVEL
выполняет вычисления времени выполнения, мы можем написать java-код в String
, чтобы получить его в этом.
String expressionStr = "x+y";
Map<String, Object> vars = new HashMap<String, Object>();
vars.put("x", 10);
vars.put("y", 20);
ExecutableStatement statement = (ExecutableStatement) MVEL.compileExpression(expressionStr);
Object result = MVEL.executeExpression(statement, vars);
Еще один вариант: https://github.com/stefanhaustein/expressionparser
Я реализовал это, чтобы иметь простой, но гибкий вариант, позволяющий обоим:
Связанный выше TreeBuilder является частью демонстрационного пакета CAS, который выполняет символический вывод. Существует также BASIC interpreter, и я начал создавать TypeScript интерпретатор, используя его.
Для запуска javascript можно использовать внешнюю библиотеку, такую как RHINO или NASHORN. И javascript может оценивать простую формулу без парсинга строки. Не влияет на производительность, если код написан хорошо. Ниже приведен пример с RHINO -
public class RhinoApp {
private String simpleAdd = "(12+13+2-2)*2+(12+13+2-2)*2";
public void runJavaScript() {
Context jsCx = Context.enter();
Context.getCurrentContext().setOptimizationLevel(-1);
ScriptableObject scope = jsCx.initStandardObjects();
Object result = jsCx.evaluateString(scope, simpleAdd , "formula", 0, null);
Context.exit();
System.out.println(result);
}
Класс Java, который может вычислять математические выражения:
package test;
public class Calculator {
public static Double calculate(String expression){
if (expression == null || expression.length() == 0) {
return null;
}
return calc(expression.replace(" ", ""));
}
public static Double calc(String expression) {
if (expression.startsWith("(") && expression.endsWith(")")) {
return calc(expression.substring(1, expression.length() - 1));
}
String[] containerArr = new String[]{expression};
double leftVal = getNextOperand(containerArr);
expression = containerArr[0];
if (expression.length() == 0) {
return leftVal;
}
char operator = expression.charAt(0);
expression = expression.substring(1);
while (operator == '*' || operator == '/') {
containerArr[0] = expression;
double rightVal = getNextOperand(containerArr);
expression = containerArr[0];
if (operator == '*') {
leftVal = leftVal * rightVal;
} else {
leftVal = leftVal / rightVal;
}
if (expression.length() > 0) {
operator = expression.charAt(0);
expression = expression.substring(1);
} else {
return leftVal;
}
}
if (operator == '+') {
return leftVal + calc(expression);
} else {
return leftVal - calc(expression);
}
}
private static double getNextOperand(String[] exp){
double res;
if (exp[0].startsWith("(")) {
int open = 1;
int i = 1;
while (open != 0) {
if (exp[0].charAt(i) == '(') {
open++;
} else if (exp[0].charAt(i) == ')') {
open--;
}
i++;
}
res = calc(exp[0].substring(1, i - 1));
exp[0] = exp[0].substring(i);
} else {
int i = 1;
if (exp[0].charAt(0) == '-') {
i++;
}
while (exp[0].length() > i && isNumber((int) exp[0].charAt(i))) {
i++;
}
res = Double.parseDouble(exp[0].substring(0, i));
exp[0] = exp[0].substring(i);
}
return res;
}
private static boolean isNumber(int c) {
int zero = (int) '0';
int nine = (int) '9';
return (c >= zero && c <= nine) || c =='.';
}
public static void main(String[] args) {
System.out.println(calculate("(((( -6 )))) * 9 * -1"));
System.out.println(calc("(-5.2+-5*-5*((5/4+2)))"));
}
}
public class StringCalculator {
public static void main(String[] args) {
String eval = "2+3*2/2+2*5/5*5";
System.out.println(calculator(eval));
}
public static int calcMulAndDiv(String val){
String nos[] = val.split("\\D+");
String opr[] = val.split("\\d+");
int res = Integer.parseInt(nos[0]);
for(int i = 1; i< opr.length ;i++){
if(opr[i].equals("*")){
res = res * Integer.parseInt(nos[i]);
}
else if(opr[i].equals("/")){
res = res / Integer.parseInt(nos[i]);
}
}
return res;
}
public static int calculator(String val){
String nos[] = val.split("[+-]");
String operators = val.replaceAll("[^+-]","");
char opr[] = operators.toCharArray();
int result = 0;
if(nos[0].contains("*") || nos[0].contains("*")){
result = calcMulAndDiv(nos[0]);
}else{
result = Integer.parseInt(nos[0]);
}
for(int i = 0 ; i < opr.length ; i++){
if(opr[i] == '+'){
if(nos[i+1].contains("*") || nos[i+1].contains("*")){
result = result + calcMulAndDiv(nos[i+1]);
}else{
result = result + Integer.parseInt(nos[i+1]);
}
}
else if(opr[i] == '-'){
if(nos[i+1].contains("*") || nos[i+1].contains("*")){
result = result + calcMulAndDiv(nos[i+1]);
}else{
result = result - Integer.parseInt(nos[i+1]);
}
}
}
return result;
}
}
public static void main(String[] args){
System.out.println("="+evaluate(args[2]));
}
public static String[] symbols = new String[]{"\\-","\\+","\\/","\\*"};
public static Integer evaluate(String exp){
System.out.print(exp);
exp = exp.trim();
boolean isint = true;
for(int i = 0; i<exp.length() && isint;i++){
if(exp.charAt(i)>'9' || exp.charAt(i) <'0'){
isint = false;
}
}
if(isint) return Integer.parseInt(exp);
for(String symbol:symbols){
String[] split = exp.split(symbol);
if(split.length>1){
int ev = evaluate(split[0]);
for(int i = 1;i<split.length;i++){
System.out.print(symbol);
int val = evaluate(split[i]);
if("\\*".equals(symbol)) ev*=val;
if("\\/".equals(symbol)) ev/=val;
if("\\+".equals(symbol)) ev+=val;
if("\\-".equals(symbol)) ev-=val;
}
return ev;
}
}
return null;
}