Всем доброго времени суток.
Ради ознакомления с разработкой под
Android решил написать простой калькулятор, который может принимать сразу несколько операторов и операндов.
Например:
2 + 3 * 4
9 / 3 + 5
Мне удалось написать калькулятор, который в целом работает, но есть одна проблема. Она заключается в том, что у меня не вышло реализовать алгоритм польской записи именно таким образом, чтобы можно было считать числа, разряд которых больше одного (15,250,1000 и т.д.).
Когда я писал калькулятор, то я действовал по следующему алгоритму:
1)Трансформируем обычную запись выражения в обратную польскую нотацию
Пример:
2 + 3 - 2 --> 2,3+2-
1 * 2 + 3 --> 1,2*3+
2)Затем с помощью Стека считаем результат
Вот код класса, который превращает из обычной записи польскую обратную запись:
public class ReversePolishNotationApp {
//VARS:
Stack<Character> stack;
String line;
String output;
//INIT:
{ stack = new Stack<Character>();
line = "";
output = "";
}
//преобразует обычную запись в обратную польскую нотацию
public void transform(String line) {
this.line = line; //получаем инфиксную запись
String[] arrayOfLines = line.split("");
int size = line.length();
for(int i = 0; i < size; i++) {
char el = line.charAt(i);
switch (el) {
case '+':
case '-':
gotOper(el,1);
break;
case '×':
case '÷':
gotOper(el,2);
break;
case '(':
stack.push(el);
break;
case ')':
gotParen(el);
break;
default:
output = output + el;
break;
}
}
while (!stack.isEmpty()) output += stack.pop();
}
private void gotOper(char currentOp, int priority) {
while (!stack.isEmpty()) {
char opTop = stack.pop();
if(opTop == '(') { stack.push(opTop); break; }
else {
int oldPriority = -1;
if(opTop == '+' || opTop == '-') oldPriority = 1;
else oldPriority = 2;
if(oldPriority < priority) { stack.push(opTop); break; }
else output = output + opTop;
}
}
stack.push(currentOp);
}
private void gotParen(char el1) {
while (!stack.isEmpty()) {
char elx = stack.pop();
if(elx == '(') break;
else output = output + elx;
}
}
public void show() {
System.out.println(output);
}
public String getNewNotation() {
return output;
}
}
А вот класс, который считает с помощью
Стека выражения:
public class Calculate {
//VARS:
private Stack<Integer> stack;
private String input;
//INIT ALL VALUES (BY CONSTRUCTOR):
public Calculate(String v) {
input = v;
stack = new Stack<Integer>();
}
public int doParse() {
char ch = ' ';
int num1, num2, interAns;
for(int i = 0; i < input.length(); i++) {
ch = input.charAt(i);
//if we works with figures (10-th notation)
if(ch >= '0' && ch <= '9') stack.push((int) ch - '0');
else {
//if we work with operators
num2 = stack.pop();
num1 = stack.pop();
switch (ch) {
case '+':
interAns = num1 + num2;
break;
case '-':
interAns = num1 - num2;
break;
case '×':
interAns = num1 * num2;
break;
case '÷':
interAns = num1 / num2;
break;
default:
interAns = 0;
break;
}
stack.push(interAns);
}
}
interAns = stack.pop(); //финальный результат
return interAns;
}
}
Ну а вот скриншот самого калькулятора:
Как правильно реализовать алгоритм обратной польской записи, чтобы можно было работать с много-разрядными числами?