Помогите посчитать перевести строку 2+2 в число
Я задал в аргумент (args) строку 2+2 и хочу чтобы прога написала в консоли 4, но вылетает ошибка. P.S я только учусь
public static void main(String[] args) {
System.out.println(Integer.parseInt(args[0]));
}
Ответы (2 шт):
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
ScriptEngineManager sem = new ScriptEngineManager();
ScriptEngine js = sem.getEngineByName("JavaScript");
System.out.println(js.eval(args[0]));
Стандартная задача. Функция eval принимает на вход выражение и возвращает его значение. Сам процесс вычисления разделён на два этапа: разборка выражения на токены - минимальные элементы имеющие самостоятельное значение, и собственно вычисление.
Разборка на токены сделана в методе tokenize. Внутри регулярное выражение, которое выделяет числа и символы '+-*/()'.
Вычисление делает класс Calc. Методы: op - сюда отправляют операции, num - cюда числа, eval - его вызывают в конце и получают значение выражения.
Calc реализует алгоритм сортировочной станции. Там внутри два стека: один для чисел, второй для операций. Я не буду тут его повторять, потребуется много места. Но рекомендую почитать - это классика алгоритмов, её стоит изучить. Приятно понимать как компьютеры разбирают алгебраические выражения. Ссылки: shunting-yard algorithm и обратная польская запись. В прошлом веке были популярны калькуляторы на обратной польской нотации, её проще обрабатывать когда мало памяти и процессор слабый.
apply - сердце калькулятора, стековая машина. Это что-то вроде ассемблера в котором всего четыре операции: выбрать из стека два числа и поместить обратно их сумму, тоже про разность, произведение и отношение.
Конечно никакой обработки ошибок нет. Учебный пример, полагаемся на пользователя.
Примеры использования. Выражения со скобками нужно брать в кавычки, это особенность работы командной строки:
$ java Calculator 2+2
4
$ java Calculator 2+2*2
6
$ java Calculator "(2+2)*2"
8
$ java Calculator "(11+2*3)/7"
2
$ java Calculator "(11+2*3)/7-3"
-1
Сама программа, 95 строк:
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Calculator {
public static void main(String[] args) {
System.out.println(eval(args[0]));
}
public static int eval(String expr) {
Calc c = new Calc();
for (String token : tokenize(expr)) {
if (token.length() == 1 && "+-*/()".contains(token)) {
c.op(token.charAt(0));
} else {
c.num(Integer.parseInt(token));
}
}
return c.eval();
}
public static List<String> tokenize(String expr) {
List<String> list = new ArrayList<String>();
Matcher m = Pattern.compile("[-+\\*/()]|[\\d]+").matcher(expr);
while (m.find()) {
list.add(m.group());
}
return list;
}
private static class Calc {
private Stack<Integer> nums = new Stack<Integer>();
private Stack<Character> ops = new Stack<Character>();
public void op(char c) {
if (c == '(') {
ops.push(c);
} else if (c == ')') {
while (true) {
char cc = ops.pop();
if (cc == '(') {
break;
}
apply(cc);
}
} else {
while (!ops.empty() && priority(ops.peek()) >= priority(c)) {
apply(ops.pop());
}
ops.push(c);
}
}
public void num(int v) {
nums.push(v);
}
public int eval() {
while (!ops.empty()) {
apply(ops.pop());
}
return nums.pop();
}
private int priority(char c) {
if (c == '+') { return 1; }
if (c == '-') { return 1; }
if (c == '*') { return 2; }
if (c == '/') { return 2; }
return 0;
}
private void apply(char c) {
if (c == '+') {
int b = nums.pop();
int a = nums.pop();
nums.push(a + b);
} else if (c == '-') {
int b = nums.pop();
int a = nums.pop();
nums.push(a - b);
} else if (c == '*') {
int b = nums.pop();
int a = nums.pop();
nums.push(a * b);
} else if (c == '/') {
int b = nums.pop();
int a = nums.pop();
nums.push(a / b);
}
}
}
}