Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Java - Калькулятор, обратная польская запись

Ответить
Настройки темы
Java - Калькулятор, обратная польская запись

Аватара для Hector

Misanthrope


Сообщения: 474
Благодарности: 38


Конфигурация

Профиль | Отправить PM | Цитировать


Собственно есть вот такой фрагмент кода:
PHP код: Выделить весь код

public Map<StringIntegerMAIN_MATH_OPERATIONS;


    {
        
MAIN_MATH_OPERATIONS = new HashMap<StringInteger>();
        
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 expressionMap<StringIntegeroperationsString 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<Stringout = new ArrayList<String>();
            
// Стек операций.
            
Stack<Stringstack = new Stack<String>();

            
// Удаление пробелов из выражения.
            
expression expression.replace(" """);

            
// Множество "символов", не являющихся операндами (операции и скобки).
            
Set<StringoperationSymbols = 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(operationindex);
                    if (
>= && nextOperationIndex) {
                        
nextOperation operation;
                        
nextOperationIndex i;
                    }
                }
                
// Оператор не найден.
                
if (nextOperationIndex == expression.length()) {
                    
findNext false;
                } else {
                    
// Если оператору или скобке предшествует операнд, добавляем его в выходную строку.
                    
if (index != nextOperationIndex) {
                        
out.add(expression.substring(indexnextOperationIndex));
                    }
                    
// Обработка операторов и скобок.
                    // Открывающая скобка.
                    
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 expressionMap<StringIntegeroperations) {
            return 
sortingStation(expressionoperations"("")");
        }
        
// вычисление 
        
public String calculateExpression(String expression) {
            
String rpn sortingStation(expressionMAIN_MATH_OPERATIONS);
            
StringTokenizer tokenizer = new StringTokenizer(rpn" ");
            
Stack<BigDecimalstack = 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(operand23RoundingMode.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) - тоже не понятно

-------
Information must be free!
Нет границ, есть только препятствия


Отправлено: 01:21, 26-02-2012

 

Аватара для lxa85

Необычный


Contributor


Сообщения: 4463
Благодарности: 994

Профиль | Сайт | Отправить PM | Цитировать


Hector, Насколько я понял, в классе реализовано однопроходное преобразование выражения в ОПЗ с использованием стека.
Т.е. надо поискать, что это за метод, и "методом научного тыка" сопоставить реализацию с теорией.
С теорией по Java к сожалению не помогу.

-------
- Я не разрешаю тебе быть плохой! Потому что плохие люди совершают плохие поступки. А это нехорошо!
(Из наставлений 5 летней девочки своей младшей сестре)


Отправлено: 07:35, 26-02-2012 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Аватара для ferget

Разный


Сообщения: 1294
Благодарности: 359

Профиль | Отправить PM | Цитировать


Цитата Hector:
проблемы с делением на ноль »
эту проблему можно решить например так
Код: Выделить весь код
if(!operand2.equals(new BigDecimal("0")))
stack.push(operand1.divide(operand2));
Цитата Hector:
и дробными числами »
а в чем именно выражается эта проблема?
что-то ее не видно

Отправлено: 08:13, 26-02-2012 | #3


Аватара для Hector

Misanthrope


Сообщения: 474
Благодарности: 38

Профиль | Отправить PM | Цитировать


ferget, если при делении второй операнд больше первого так, что в результате не получается целой части (например 6/9), тогда программа вылетает. я пытался решить это:
Код: Выделить весь код
else if (token.equals("/")) { 
                        if (operand1.compareTo(operand2)==-1) 
                            stack.push(operand1.divide(operand2, 3, RoundingMode.HALF_UP)); 
                        else 
                            stack.push(operand1.divide(operand2));
но в этом случае у всех следующих чисел всегда будет 3 знака после запятой независимо от последующих операций (выглядит так - 5.000)

-------
Information must be free!
Нет границ, есть только препятствия


Отправлено: 11:09, 26-02-2012 | #4



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » Java - Калькулятор, обратная польская запись

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
Вопрос по коду PHP(обратная связь) zion87 Вебмастеру 0 10-02-2012 23:35
[решено] JS. Обратная транслитерация. VeshchiyOleg Вебмастеру 1 27-01-2007 21:00
польская клавиатура? delphispb Microsoft Windows 2000/XP 1 12-10-2005 18:38




 
Переход