Преобразование обратной польской записи

Есть ли способ интерпретировать обратную польскую нотацию в «нормальную» математическую нотацию при использовании C++ или C#? Я работаю в инженерной фирме, поэтому они время от времени используют RPN, и нам нужен способ его преобразовать. Какие-либо предложения?

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
9
0
11 119
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

В C# нет встроенной поддержки синтаксического анализа обратной польской нотации (RPN). Вам нужно будет написать свой собственный синтаксический анализатор или найти его в Интернете.

Существуют десятки руководств по преобразованию постфиксной формы (RPN) в инфиксную (алгебраическое уравнение). Взгляните на это, возможно, вы найдете его полезным, и вы можете попытаться «реконструировать» его, чтобы преобразовать постфиксные выражения в инфиксную форму, имея в виду, что может быть несколько инфиксных обозначений для данной постфиксной. Есть очень мало полезных примеров, которые на самом деле обсуждают преобразование постфикса в инфиксный. Вот запись из двух частей, которая мне показалась очень полезной. Также в нем есть псевдокод:

Ссылка говорит о том, как преобразовать инфикс в постфикс, а не наоборот ....

Chris Jester-Young 22.09.2008 10:46

Я обновил свой ответ. Хотя я не смог найти точного решения, я добавил ссылки, которые должны помочь в его формулировании.

Abbas 18.03.2013 23:25
Ответ принят как подходящий

Да. Подумайте, как работает калькулятор RPN. Теперь вместо вычисления значения вы добавляете операцию в дерево. Так, например, 2 3 4 + *, когда вы попадаете в +, вместо того, чтобы помещать 7 в стек, вы помещаете (+ 3 4) в стек. И аналогично, когда вы дойдете до * (на этом этапе ваш стек будет выглядеть как 2 (+ 3 4) *), он станет (* 2 (+ 3 4)).

Это префиксная запись, которую затем нужно преобразовать в инфиксную. Обойдите дерево слева направо, сначала в глубину. Для каждого «внутреннего уровня», если приоритет оператора ниже, вам придется заключить операцию в скобки. Здесь вы скажете 2 * (3 + 4), потому что + имеет более низкий приоритет, чем *.

Надеюсь это поможет!

Обновлено: есть тонкость (помимо того, что не учитываются унарные операции в приведенном выше): я предполагал левоассоциативные операторы. Для правоассоциативных (например, **) вы получите разные результаты для 2 3 4 ** **(** 2 (** 3 4)) и 2 3 ** 4 **(** (** 2 3) 4).

При восстановлении инфикса из дерева оба случая показывают, что приоритет не требует заключения в скобки, но на самом деле последний случай необходимо заключить в скобки ((2 ** 3) ** 4). Таким образом, для правоассоциативных операторов левая ветвь должна иметь более высокий приоритет (а не более высокий или равный), чтобы избежать заключения в скобки.

Кроме того, есть еще одна мысль, что вам нужны скобки для правой ветви операторов - и /.

Алгоритм маневрового двора используется для преобразования инфиксных (т. Е. Алгебраических) значений в RPN. Это противоположно тому, что вы хотите.

Вы можете привести мне пример вашего ввода RPN? Я опытный пользователь / программист калькуляторов HP. Я предполагаю, что у вас есть стек, содержащий все входы и операторы. Я предполагаю, что вам нужно восстановить дерево выражения, а затем пройти по нему, чтобы сгенерировать инфиксную форму.

Да, создание дерева выражений - это именно то, что нужно. :-) У меня был способ сначала преобразовать в префикс, но, возможно, есть методы прямого преобразования в инфикс.

Chris Jester-Young 22.09.2008 10:25

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

Если у вас есть исходный текст (строка / ы), который вы хотите преобразовать из RPN (постфиксная нотация) в «нормальную нотацию» (инфиксную), это, безусловно, возможно (и, вероятно, не слишком сложно).

RPN был разработан для машин на основе стека, так как способ представления операции («2 + 3» -> «2 3 +») соответствовал тому, как она фактически выполнялась на оборудовании (поместите «2» в стек, нажмите «3» "в стек, вынуть два верхних аргумента из стека и добавить их, вернуть в стек).

По сути, вы хотите создать синтаксическое дерево из вашего RPN, создав 2 выражения, которые вы хотите оперировать с «листовыми узлами», и саму операцию, которая последует после этого, «родительский узел». Это, вероятно, будет сделано путем рекурсивного просмотра вашей входной строки (вы, вероятно, захотите убедиться, что подвыражения правильно заключены в круглые скобки для дополнительной ясности, если они еще не были).

Когда у вас есть это синтаксическое дерево, вы можете вывести префиксную, инфиксную или постфиксную нотацию, просто выполнив предварительный, пост-упорядоченный или упорядоченный обход этого дерева (опять же, заключив вывод в скобки для ясности, если это необходимо).

Дополнительную информацию можно найти здесь.

Если вы умеете читать рубин, вы найдете несколько хороших решений для этого здесь

Я только что написал версию на Java, это здесь и еще одну на Objective-C, а не на здесь.

Возможный алгоритм: если у вас есть стек с вводом в rpn, когда пользователь вводит его, например 8, 9, *. Вы перебираете массив от первого до последнего и всегда удаляете текущий элемент. Этот элемент вы оцените. Если это операнд, вы добавляете его в стек результатов. Когда это оператор, вы дважды вставляете стек результатов (для бинарных операций) для операндов и записываете строку результата в стек результатов.

В примере ввода «8, 9, +, 2, *» вы получаете эти значения в стеке результатов (квадратные скобки для обозначения отдельных элементов):

шаг 1: [8]

шаг 2: [8], [9]

шаг 3: [(8 + 9)]

шаг 4: [(8 + 9)], [2]

шаг 5: [(8 + 9) * 2]

Когда стек ввода пуст, вы закончите, и единственный элемент resultStack - ваш результат. (Обратите внимание, однако, что ввод может содержать несколько записей или таких, которые не имеют смысла, например, ведущая операция: "+ 2 3 /".)

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

Перенести его на C# очень просто.

Другие вопросы по теме