Калькулятор, обратная польская запись
Собственно есть вот такой фрагмент кода:
PHP код:
public Map<String, Integer> MAIN_MATH_OPERATIONS;
{
MAIN_MATH_OPERATIONS = new HashMap<String, Integer>();
MAIN_MATH_OPERATIONS.put("*", 1);
MAIN_MATH_OPERATIONS.put("/", 1);
MAIN_MATH_OPERATIONS.put("+", 2);
MAIN_MATH_OPERATIONS.put("-", 2);
}
public class ExpressionUtils {
// из инфиксной нотации в обратную польскую
public String sortingStation(String expression, Map<String, Integer> operations, String leftBracket,
String rightBracket) {
if (expression == null || expression.length() == 0)
throw new IllegalStateException("Expression isn't specified.");
if (operations == null || operations.isEmpty())
throw new IllegalStateException("Operations aren't specified.");
// Выходная строка, разбитая на "символы" - операции и операнды..
List<String> out = new ArrayList<String>();
// Стек операций.
Stack<String> stack = new Stack<String>();
// Удаление пробелов из выражения.
expression = expression.replace(" ", "");
// Множество "символов", не являющихся операндами (операции и скобки).
Set<String> operationSymbols = new HashSet<String>(operations.keySet());
operationSymbols.add(leftBracket);
operationSymbols.add(rightBracket);
// Индекс, на котором закончился разбор строки на прошлой итерации.
int index = 0;
// Признак необходимости поиска следующего элемента.
boolean findNext = true;
while (findNext) {
int nextOperationIndex = expression.length();
String nextOperation = "";
// Поиск следующего оператора или скобки.
for (String operation : operationSymbols) {
int i = expression.indexOf(operation, index);
if (i >= 0 && i < nextOperationIndex) {
nextOperation = operation;
nextOperationIndex = i;
}
}
// Оператор не найден.
if (nextOperationIndex == expression.length()) {
findNext = false;
} else {
// Если оператору или скобке предшествует операнд, добавляем его в выходную строку.
if (index != nextOperationIndex) {
out.add(expression.substring(index, nextOperationIndex));
}
// Обработка операторов и скобок.
// Открывающая скобка.
if (nextOperation.equals(leftBracket)) {
stack.push(nextOperation);
}
// Закрывающая скобка.
else if (nextOperation.equals(rightBracket)) {
while (!stack.peek().equals(leftBracket)) {
out.add(stack.pop());
if (stack.empty()) {
throw new IllegalArgumentException("Unmatched brackets");
}
}
stack.pop();
}
// Операция.
else {
while (!stack.empty() && !stack.peek().equals(leftBracket) &&
(operations.get(nextOperation) >= operations.get(stack.peek()))) {
out.add(stack.pop());
}
stack.push(nextOperation);
}
index = nextOperationIndex + nextOperation.length();
}
}
// Добавление в выходную строку операндов после последнего операнда.
if (index != expression.length()) {
out.add(expression.substring(index));
}
// Пробразование выходного списка к выходной строке.
while (!stack.empty()) {
out.add(stack.pop());
}
StringBuffer result = new StringBuffer();
if (!out.isEmpty())
result.append(out.remove(0));
while (!out.isEmpty())
result.append(" ").append(out.remove(0));
return result.toString();
}
public String sortingStation(String expression, Map<String, Integer> operations) {
return sortingStation(expression, operations, "(", ")");
}
// вычисление
public String calculateExpression(String expression) {
String rpn = sortingStation(expression, MAIN_MATH_OPERATIONS);
StringTokenizer tokenizer = new StringTokenizer(rpn, " ");
Stack<BigDecimal> stack = new Stack<BigDecimal>();
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
// Операнд.
if (!MAIN_MATH_OPERATIONS.keySet().contains(token)) {
stack.push(new BigDecimal(token));
} else {
BigDecimal operand2 = stack.pop();
BigDecimal operand1 = stack.empty() ? BigDecimal.ZERO : stack.pop();
if (token.equals("*")) {
stack.push(operand1.multiply(operand2));
} else if (token.equals("/")) {
if (operand1.compareTo(operand2)==-1)
stack.push(operand1.divide(operand2, 3, RoundingMode.HALF_UP));
else
stack.push(operand1.divide(operand2));
} else if (token.equals("+")) {
stack.push(operand1.add(operand2));
} else if (token.equals("-")) {
stack.push(operand1.subtract(operand2));
}
}
}
if (stack.size() != 1)
throw new IllegalArgumentException("Expression syntax error.");
return stack.pop().toString();
}
/**
* Закрытый конструктор класса.
*/
private ExpressionUtils() {
}
}
это класс из калькулятора написанного под Android, он выполняет преобразование выражения из инфиксной нотации в обратную польскую, а потом вычисляет его. код немного не работает (проблемы с делением на ноль и дробными числами), поэтому надо поправить. Проблема в том, что о Java я не знаю практически ничего.
Интересуют следующие моменты:
Код:
public Map<String, Integer> MAIN_MATH_OPERATIONS;
{
MAIN_MATH_OPERATIONS = new HashMap<String, Integer>();
MAIN_MATH_OPERATIONS.put("*", 1);
MAIN_MATH_OPERATIONS.put("/", 1);
MAIN_MATH_OPERATIONS.put("+", 2);
MAIN_MATH_OPERATIONS.put("-", 2);
}
что это за структура данных? где почитать про нее?
List<String> out = new ArrayList<String>() - это коллекции, или я не прав? опять же, где почитать?
Set<String> operationSymbols = new HashSet<String>(operations.keySet()) - даже догадок нету
for (String operation : operationSymbols) - тоже не понятно
|