Понимание обратной польской записи для домашнего задания? - PullRequest
0 голосов
/ 27 апреля 2010

Меня попросили написать простой калькулятор обратной польской нотации на C как часть домашнего задания. У меня проблемы с пониманием RPN. Можете ли вы помочь мне понять обратную польскую запись? Кроме того, любые советы о том, как подойти к этой проблеме, будут с благодарностью.

Ответы [ 4 ]

12 голосов
/ 27 апреля 2010

Обратная польская запись - это особый способ написания выражений, в котором вы сначала записываете значения, а затем выполняете операцию, которую хотите выполнить. Так, например, чтобы добавить цифры 3 и 4, вы должны написать 3 4 +.

Итак, для написания калькулятора RPN вам понадобится

  • Средство приема ввода, например, из консоли
  • Средство токенизация ввода (для того, что вы делаете, вероятно, достаточно разбить пробел)
  • A стек для хранения значений (операндов) (таких как 3 и 4 в приведенном выше)
  • Словарь операций

Тогда цикл становится, по сути:

while (there's a token available) {
    token = get_the_token
    if (token is known operator) {
        get the number of values from stack this operation requires (usually two); fail if stack doesn't have enough
        perform operation on values
        push result on the stack
    }
    else if (token is valid value) {
        push it on the stack
    }
    else {
        show error: invalid input
    }
}
show result remaining on stack

Вы можете понять, почему RPN делает написание калькулятора довольно простым: вам не нужно беспокоиться о наличии операторов между значениями, с которыми они работают, и вам не нужны круглые скобки для группировки, как при использовании более распространенного инфикс форма записи. Например, когда мы пишем (10 + (4 * 2)) / 9 в инфиксной записи, мы пишем 10 4 2 * + 9 / в RPN. Ваш калькулятор будет обрабатывать эти токены следующим образом:

  • 10: это значение, поместите его в стек
  • 4: это значение, поместите его в стек
  • 2: это значение, поместите его в стек
  • *: это оператор, вытолкните 2 и 4 из стека и умножьте их (4 * 2); поместите результат (8) в стек
  • +: это оператор, вытолкните 8 и 10 из стека и добавьте их (10 + 8); поместите результат (18) в стек
  • 9: это значение, поместите его в стек
  • /: это оператор, вытолкните 9 и 18 из стека и разделите их (18 / 9); поместите результат (2) в стек (обратите внимание, что значение в верхней части стека - в данном случае - 9 - это делитель, следующее значение под ним - 18 - это дивиденд)
  • Конец ввода, показать значения в стеке: 2
4 голосов
/ 27 апреля 2010

Обратная польская запись - это форма записи для математических выражений, где операторы следуют за операндами. При оценке выражения RPN каждый двоичный оператор ссылается на два операнда , непосредственно предшествующих ему . Возьмем это выражение RPN, например:

5 4 3 + *

Начните сканирование выражения слева, пока не дойдете до первого оператора, который является +. Этот оператор имеет операнды 4 и 3 (те, которые идут непосредственно перед ним), поэтому мы можем заменить все три с результатом, 7. (Обратите внимание, что скобки не нужны, но я использую их, чтобы прояснить смысл).

5 (4 3 +) * => 5 7 *

Теперь у нас есть оператор * и два операнда 5 и 7 (что в действительности является результатом 4 + 3). Мы умножаем 5 и 7, и все выражение оценивается как 35.

5 7 * => 35

Это общий алгоритм для вычисления любого выражения RPN.


Выражения RPN особенно хорошо подходят для анализа компьютерами, использующими структуру данных, известную как стек .

Стек - это упорядоченная коллекция, один конец которой обозначен как «верх». Элементы всегда добавляются в стек или удаляются из стопки сверху. Таким образом, единственный элемент, который нужно удалить, это всегда элемент, который был добавлен последним. По этой причине стеки иногда называют Last In, First Out (или LIFO), поскольку последний элемент, помещенный в стек, находится сверху и, таким образом, будет удален первым.

В C вы можете реализовать стек с двумя переменными: массивом (достаточно большим, чтобы вместить максимальное количество элементов, которое, как вы ожидаете, может понадобиться в стеке), и целым числом, которое указывает, какой индекс в массиве в настоящее время является верхним.

Стеки хорошо подходят для оценки выражения RPN, потому что, когда вы сталкиваетесь с оператором, оно всегда применяется к самым последним встречаемым операндам. Так как вы просматриваете выражение слева, вы можете сохранить операнды в стеке. Возьмем наш пример снова:

5 4 3 + *

Первым делом здесь операнд (5), поэтому поместите его в стек (который изначально пуст). Затем мы встречаем 4 и помещаем его в стек. Это становится новой вершиной. Затем мы делаем то же самое с 3.

5 4 3 <-- top
+ * // Remaining expression

Далее мы сталкиваемся с оператором +. Мы знаем, что это относится к ранее обнаруженным операндам, но где мы можем их найти? Конечно, на вершине стека! Вытяните 3 и 4 из стека и добавьте их, чтобы получить 7. Но что делать с результатом? Ну, это может быть операнд другого оператора, поэтому поместите его обратно в стек (точно так же, как мы заменили операнды и оператор результатом, когда мы вычислили выражение вручную):

5 7 <-- top
* // Remaining expression

Теперь мы видим *. Еще раз, самые последние операнды - это два верхних операнда в стеке. Мы выталкиваем их и умножаем, чтобы получить 35, а затем помещаем их обратно в стек.

35 <-- top
// No expression remaining

На данный момент мы достигли конца выражения, и единственное, что в стеке - это результат. Были сделаны! Вы можете видеть, как стек операндов «сохраняет» первые обнаруженные операнды, пока не встретится соответствующий оператор, который может находиться на другом конце выражения.

Если бы мы достигли конца и обнаружили, что в стеке осталось более одного числа, это означало бы, что в выражении слишком много операндов и недостаточно операторов. С другой стороны, если бы мы столкнулись с оператором в какой-то момент и имели меньше двух операндов в стеке, мы бы знали, что в выражении слишком много операторов и недостаточно операндов.

2 голосов
/ 27 апреля 2010

Вы можете найти учебник по http://www.codeproject.com/KB/cs/Reverse_Polish_Notation.aspx

0 голосов
/ 29 октября 2010

Вы можете найти простую реализацию на http://expressionoasis.vedantatree.com/

...