2015-04-05 4 views
0

Я пытался выяснить ошибки моего кода безрезультатно. Я должен кодировать инфикс для постфиксного переводчика, в дополнение к оценке выражения postfix. Мой код работает, но, к сожалению, он не возвращает правильное значение.Postfix оценщик не возвращает правильные результаты

У меня есть графический интерфейс калькулятора, который вызывает код, показанный ниже всякий раз, когда знак равенства нажат. Калькулятор передает в качестве аргумента строку, разделенную пробелами. Затем я использую Stenken Tokenizer в этой пробельной разделительной строке и работаю оттуда. Я могу предоставить код для графического интерфейса калькулятора, если это поможет.

Моя проблема кроется в ответе, который дает калькулятор. Например, если я ввожу (5 + 2), калькулятор возвращает 2 в качестве ответа, и если я снова нажимаю знак равенства, он возвращает 5 в качестве ответа. Если я ввожу (5 * 2) + (3 * 9), он возвращает 9 в качестве ответа, и если я снова нажимаю знак равенства, он возвращает 5 как asnwer. Я много раз пробовал использовать свой код, но, к сожалению, я не смог найти свою ошибку. Любая помощь будет принята с благодарностью!

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Я осведомлен о боковой заметке об использовании строкового токенизатора. Я бы использовал что-то еще, но это одно из требований. Я еще не выполнил проверку на наличие ошибок или проверку приоритета, потому что я хочу убедиться, что он работает правильно, полагая, что вход правильный и не слишком сложный. Кроме того, я знаю, что мой код не будет правильно обрабатывать что-то вроде (5 + 2) -1 из-за отсутствия скобок вокруг 1. Но опять-таки это не сработает с чем-то еще более простым, чем это. . Я буду беспокоиться об этом, как только я смогу заставить его работать с более простым вводом. Наконец, это действительно домашнее задание, но, пожалуйста, не думайте, что я хочу, чтобы это было сделано для меня полностью. Было бы очень полезно оценить несколько указателей.

Вот мой код:

public class ExpressionEvaluator { 

Stack<String> myStack = new Stack<>(); 
Queue<String> myQueue = new Queue<>(); 

String curToken; //Current token of my tokenized string. 
double temp1; //Place holder for first value of the calc section. 
double temp2; //Place holder for second value of the calc section. 

public String processInput(String s) { 

    StringTokenizer st = new StringTokenizer(s); 

    while (st.hasMoreTokens()) { 

     curToken = st.nextToken(); 

     if (openParenthesis(curToken)) { 
      myStack.push(curToken); 
     } 

     if (closeParenthesis(curToken)) { 
      do { 
       myQueue.enqueue(myStack.pop()); 
      } while (!openParenthesis(myStack.peek())); 
     } 

     if (isOperator(curToken)) { 
      while (!myStack.isEmpty() && !openParenthesis(myStack.peek())) { 
       myQueue.enqueue(myStack.pop()); 
      } 
      myStack.push(curToken); 
     } 
     if (isDouble(curToken)) { 
      myQueue.enqueue(curToken); 
     } 
    } 

    while (!myStack.isEmpty()) { 
     myQueue.enqueue(myStack.pop()); 
    } 

    while (!myQueue.isEmpty()) { 
     if (isDouble(myQueue.peek())) { 
      myStack.push(myQueue.dequeue()); 
     } 

     else if (isOperator(myQueue.peek())) { 
      temp1 = Double.parseDouble(myStack.pop()); 
      temp2 = Double.parseDouble(myStack.pop()); 
      myStack.push(Double.toString(calc(temp1, temp2))); 
     } 

     else { 
      myQueue.dequeue(); 
     } 
    } 
    return myStack.pop(); 
} 

//Private methods used to simplify/clarify some things. 


//Checks if input is an operator, returns true if it is 
private boolean isOperator(String str) { 
    if (str == "+") {return true;} 
    else if (str == "-") {return true;} 
    else if (str == "*") {return true;} 
    else if (str == "/") {return true;} 
    else if (str == "^") {return true;} 
    else {return false;} 
} 

//Checks if input is an open parenthesis "(", returns true if it is 

private boolean openParenthesis(String str) { 
    if (str == "(") {return true;} 
    else {return false;} 
} 

//Checks if input is a close parenthesis ")", returns true if it is 

private boolean closeParenthesis(String str) { 
    if (str == ")") {return true;} 
    else {return false;} 
} 

//Checks if input is a double, returns true if it is 
//I actually got this method from Stack Overflow, so thanks! 

private boolean isDouble(String str) { 
    try { 
     Double.parseDouble(str); 
     return true; 
    } catch (NumberFormatException e) { 
     return false; 
    } 
} 

//Method used to actually do the calculations. I have 
//a feeling this is where my problem is, but I can't 
//think of a way to fix it. 

private double calc(double a, double b) { 
    String op = myQueue.dequeue(); 

    if (op == "+") {return a+b;} 
    else if (op == "-") {return a-b;} 
    else if (op == "*") {return a*b;} 
    else if (op == "/") {return a/b;} 
    else if (op == "^") {return Math.pow(a, b);} 
    else {throw new UnknownElementException(null, "ERROR");} 
} 
} 

Извините за странный отступа. Любая помощь будет принята с благодарностью!

ответ

1

Существует алгоритм с именем Shunting-yard, который указывает, как преобразовать нотацию инфикса в нотацию фиксированной записи (также называемую «обратная польская нотация»). Тогда вам не придется беспокоиться о приоритете оператора.

Он использует очередь и стек. В основном, когда вы сталкиваетесь с цифрой, вы добавляете ее в очередь. И когда вы сталкиваетесь с операторами, вы нажимаете их на стек.

Вы можете найти подробный алгоритм здесь: Shunting-Yard Algorithm

После того, как в обратной польской записи вы можете легко оценить его, как описано здесь: Postfix evaluation algorithm

+0

Спасибо, я посмотрю на это! – kevinivan05

0

я, наконец, понял это! Я использовал == вместо .equals() для сравнения строк в моих методах isOperator, closeParenthesis и openParenthesis.