Обратная польская записьОбра́тная по́льская за́пись (англ. Reverse Polish notation, RPN) — форма записи математических и логических выражений, в которой операнды расположены перед знаками операций. Также именуется как обратная бесскобочная запись, постфиксная нотация, бесскобочная символика Лукасевича, польская инверсная запись, ПОЛИЗ. Стековой машиной называется алгоритм, проводящий вычисления по обратной польской записи (см. ниже пример вычисления выражений). ИсторияОбратная польская нотация (ОПН) была разработана австралийским философом и специалистом в области теории вычислительных машин Чарльзом Хэмблином в середине 1950-х на основе польской нотации, которая была предложена в 1920 году польским математиком Яном Лукасевичем. Работа Хэмблина была представлена на конференции в июне 1957 и издана в 1957 и 1962. Первыми компьютерами, поддерживающими обратную польскую нотацию, были KDF9 от English Electric Company, который был анонсирован в 1960 и выпущен (появился в продаже) в 1963, и американский Burroughs B5000, анонсирован в 1961, выпущен в том же 1963. Один из проектировщиков B5000, Р. С. Бартон, позже написал, что разработал обратную польскую запись независимо от Хэмблина, примерно в 1958, в процессе чтения книги по символьной логике, и до того как познакомился с работой Хэмблина. Компания Friden перенесла ОПН в настольные калькуляторы, выпустив в июне 1964 модель EC-130. А в 1968 инженеры Hewlett-Packard разработали настольный калькулятор 9100A с поддержкой ОПН. Этот калькулятор сделал обратную польскую нотацию популярной среди учёных и инженеров, даже несмотря на то, что в ранней рекламе 9100A ОПН не упоминалась. В 1972 калькулятор HP-35 с поддержкой ОПН стал первым научным карманным калькулятором. В 1971 году появился оригинальный язык программирования Forth, языковая машина которого имеет двухстековую структуру и где все вычисления проводятся на стеке. В этом языке ОПН является естественным способом записи любых операций с данными, хотя возможна, при желании, реализация и обычной (инфиксной) записи арифметических операций. ОПН применялась в советском инженерном калькуляторе Б3-19М (совместная разработка с ГДР), выпущенном в 1976 году. Все выпускаемые в СССР вплоть до конца 1980-х годов программируемые микрокалькуляторы, за исключением «Электроника МК-85» и «Электроника МК-90», использовали ОПН — она проще реализовывалась и позволяла обойтись в программировании вычислений меньшим числом команд, по сравнению с обычной алгебраической нотацией, а количество программной памяти в этих моделях всегда было критическим ресурсом. ОПН используется в современных российских программируемых калькуляторах «Электроника МК-152» и «Электроника МК-161», что обеспечивает их совместимость с программами, написанными для советских калькуляторов. ОпределениеЧтобы дать индуктивное определение постфиксной нотации[1], обозначим выражения в инфиксной нотации , , , эквивалентные им выражения в постфиксной нотации , , соответственно; — произвольный бинарный оператор, тогда: 1. Если — переменная или константа, то есть . 2. Если — выражение вида , то есть . 3. Если — выражение вида , то есть . ОписаниеОтличительной особенностью обратной польской нотации является то, что все аргументы (или операнды) расположены перед знаком операции. В общем виде запись выглядит следующим образом:
Например, рассмотрим вычисление выражения
Очевидное расширение обратной польской записи на унарные, тернарные и операции с любым другим количеством операндов: при использовании знаков таких операций в вычислении выражения операция применяется к соответствующему числу последних встретившихся операндов. Особенности обратной польской записи следующие:
Вычисления на стекеОбщий порядокАвтоматизация вычисления выражений в обратной польской нотации основана на использовании стека. Алгоритм вычисления для стековой машины элементарен:
Реализация стековой машины, как программная, так и аппаратная, чрезвычайно проста и может быть очень эффективной. Обратная польская запись совершенно унифицирована — она принципиально одинаково записывает унарные, бинарные, тернарные и любые другие операции, а также обращения к функциям, что позволяет не усложнять конструкцию вычислительных устройств при расширении набора поддерживаемых операций. Это и послужило причиной использования обратной польской записи в некоторых научных и программируемых микрокалькуляторах. Пример вычисления выраженийИнфиксное выражение в ОПН может быть записано так: Вычисление производится слева направо, ввод интерпретируется как указано в приведённой ниже таблице (указано состояние стека после выполнения операции, вершина стека выделена красным цветом):
Результат, 15, в конце вычислений находится на вершине стека. Клавиша «Ввод» (обозначаемая на калькуляторах как «Enter» или символом «↑») выполняет роль разделителя операндов, когда два операнда непосредственно следуют друг за другом. Если за операндом следует знак операции, то её нажатие не требуется, это сокращает количество действий, которые нужно выполнить для получения результата. Преобразование из инфиксной нотацииЭдсгер Дейкстра изобрёл алгоритм для преобразования выражений из инфиксной нотации в ОПЗ. Алгоритм получил название «сортировочная станция», за сходство его операций с происходящим на железнодорожных сортировочных станциях. Как и алгоритм вычисления ОПЗ, алгоритм сортировочной станции основан на стеке. В преобразовании участвуют две текстовых переменных: входная и выходная строки. В процессе преобразования используется стек, хранящий ещё не добавленные к выходной строке операции. Преобразующая программа читает входную строку последовательно символ за символом (символ — это не обязательно буква), выполняет на каждом шаге некоторые действия в зависимости от того, какой символ был прочитан. Простой примерВход: Добавим Помещаем Добавим Мы прочитали всё выражение, теперь выталкиваем все оставшиеся в стеке операции в выходную строку. В нашем примере в стеке содержится только Выходная строка: В данном примере проявляются некоторые правила: все числа переносятся в выходную строку сразу после прочтения; когда выражение прочитано полностью, все оставшиеся в стеке операции выталкиваются в выходную строку. Алгоритм
Ограничения и модификацииАлгоритм предполагает, что исходная строка корректна (проверяются не все ошибки), и все префиксные/постфиксные функции унарные. Модификацию для многоместных функций с фиксированным количеством аргументов см. в основной статье. Для операций вроде −x, являющихся как бинарными, так и унарными, нужна модификация: при обнаружении подобной операции система смотрит на предыдущий символ и определяет, чем будет минус, бинарной операцией или унарной функцией. Соответственно, в стеке и ОПЗ нужны разные символы для бинарного и унарного минуса. Сложный пример
Вход: 3 + 4 * 2 / (1 - 5)^2 Читаем «3» Добавим «3» к выходной строке Выход: 3 Читаем «+» Кладём «+» в стек Выход: 3 Стек: + Читаем «4» Добавим «4» к выходной строке Выход: 3 4 Стек: + Читаем «*» Кладём «*» в стек Выход: 3 4 Стек: + * Читаем «2» Добавим «2» к выходной строке Выход: 3 4 2 Стек: + * Читаем «/» Выталкиваем «*» из стека в выходную строку, кладём «/» в стек Выход: 3 4 2 * Стек: + / Читаем «(» Кладём «(» в стек Выход: 3 4 2 * Стек: + / ( Читаем «1» Добавим «1» к выходной строке Выход: 3 4 2 * 1 Стек: + / ( Читаем «−» Кладём «−» в стек Выход: 3 4 2 * 1 Стек: + / ( − Читаем «5» Добавим «5» к выходной строке Выход: 3 4 2 * 1 5 Стек: + / ( - Читаем «)» Выталкиваем «−» из стека в выходную строку, выталкиваем «(» Выход: 3 4 2 * 1 5 − Стек: + / Читаем «^» Кладём «^» в стек Выход: 3 4 2 * 1 5 − Стек: + / ^ Читаем «2» Добавим «2» к выходной строке Выход: 3 4 2 * 1 5 − 2 Стек: + / ^ Конец выражения Выталкиваем все элементы из стека в строку Выход: 3 4 2 * 1 5 − 2 ^ / + Оптимизация выраженийЕсли вы пишете интерпретатор, то выходная строка, полученная после преобразования исходного выражения в обратную польскую нотацию, может храниться вместо исходного выражения для последующей интерпретации. Обратная польская нотация также позволяет компьютеру упрощать выражения. Пример алгоритма упрощения выраженияРассмотрим алгоритм, который осуществляет предвычисление констант в выражении. Дано выражение в ОПН. Нам понадобится стек для хранения смешанных данных (чисел и операторов). Алгоритм подобен тому, который применяется для вычисления выражений. Мы просматриваем выражение слева направо. Пока есть символы для чтения:
После того, как всё выражение просмотрено, то, что осталось в стеке, является оптимизированым выражением (операторы выражения лежат в стеке в обратном порядке). Пример работы алгоритмаВыражение
Инфиксная нотация: exp(-1/2*x)
Обратная Польская нотация: -1 2 / x * exp
Читаем: «-1»
Кладём «-1» в стек
Стек: -1
Читаем: «2»
Кладём «2» в стек
Стек: -1 2
Читаем: «/»
Вычисляем частное, результат кладём в стек
Стек: -0.5
Читаем: «x»
Кладём «x» в стек со значением null
Стек: -0.5 x(null)
Читаем: «*»
Кладём «*» в стек со значением null
Стек: -0.5 x(null) *(null)
Читаем «exp»
Кладём «exp» в стек со значением null
Стек: -0.5 x(null) *(null) exp(null)
Результат оптимизации: -0.5 x * exp
Данный метод, очевидно, не включает всех возможных способов оптимизации. Примеры реализацииВ статье «Обратная польская запись: примеры реализации» собраны примеры реализации обратной польской записи на различных языках программирования. Практические реализацииВ качестве практического применения данной методики можно привести организацию байт-кода конфигураций прикладных решений системы 1С:Предприятие. Официального подтверждения компания 1С не даёт, но пользователи данной системы на специализированных форумах приводят доказательства и алгоритмы, позволяющие декомпилировать исходные тексты. Литература
Примечания
См. такжеЯзыки программирования, использующие ОПН в качестве основной:
Ссылки
|