2009-10-09 2 views
10

Каков наилучший способ реализации программы python, которая примет строку и выведет ее результат в соответствии с приоритетом оператора (например: «4 + 3 * 5» выведет 19). Я искал пути решения этой проблемы, но они были слишком сложными, и я ищу (относительно) простой.Оценка выражения математики

уточнение: мне нужно что-то немного более продвинутое, чем eval() - я хочу иметь возможность добавлять других операторов (например, максимальный оператор - 4 $ 2 = 4) или, кроме того, меня больше интересует это академически, чем профессиональная - Я хочу знать как для этого.

+1

http://docs.python.org/reference/simple_stmts.html#exec – nlucaroni

+1

Посмотрите на: http: // stackoverflow.com/questions/400050/read-and-running-a-Mathematical-expression-in-python –

+1

Попробуйте «оценить» вместо «решить», что предполагает возможность «x» указать «4x - 6 = 4». – dmckee

ответ

16

Если вы «академически заинтересованы», вы хотите узнать, как написать парсер с приоритетом оператора.

Simple Top-Down Parsing in Python - хорошая статья, которая создает примерный синтаксический анализатор, чтобы сделать именно то, что вы хотите сделать: оценить математические выражения.

Я могу порекомендовать пропустить свой собственный первый синтаксический анализатор - это один из тех, «ах», , это, как это работает «моменты!

+0

Я очень быстро посмотрел, и кажется, что статья, которую вы связали, реализует шаблон интерпретатора в Python. –

1

Я не очень хорошо знаком с Python и любыми чрезвычайно питоническими методами, но вы можете посмотреть на Interpreter pattern, который определен в книге «Банда четырех». Он предназначен для обработки «языка», а математические выражения следуют определенному языку с правилами. Фактически, пример в Википедии на самом деле представляет собой реализацию Java калькулятора RPN.

+18

Так что их вызов разбора «шаблона» теперь тоже? Это должно быть самым распространенным словом в информатике ... – Noldorin

+0

Это не просто синтаксический анализ. Он анализирует «предложения» на данном «языке» чистым, понятным способом. –

+1

@Thomas: На самом деле это не более конкретный, чем общий синтаксический анализ. Я имею в виду, что все разборки подразумевают «предложения»; и любой достойный парсер ia чистый/понятный, по крайней мере в той или иной форме. (См. Рекурсивный спуск в качестве примера.) Кроме того, s/their/they: P – Noldorin

1

Вот что делает функция «eval» в Python.

result = eval(expression) 

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

result = eval(expression, {'__builtins__': None}, {}) 

Но это только если вам нужна безопасность, то есть, если вы позволите никому ввести любое выражение.

Конечно, поскольку вы таким образом блокируете все переменные locla из-за использования, то у вас нет каких-либо переменных для использования, поэтому для этого вам необходимо передать только те переменные, к которым следует обращаться в словарях.

vars = {'__builtins__': None, 'x': x} 
result = eval(expression, vars, {}) 

или аналогичный.

+1

Проблема с eval возникает, когда выражение = "system.os (rm -rf \)". Если вы запустите его как root в * nix, стрела идет по машине. Или, если это эквивалент Windows, тем более, что слишком много людей работают под управлением Windows в качестве администратора. –

+2

Только если вы выполнили 'из системы импорта os' и не указали каталог глобальных и локальных ресурсов. Что я делаю в своих примерах по этой причине. –

+0

Внутри выражения вы можете снова импортировать систему из os, а затем использовать ее. Так что да, мой пример будет работать, только если вы уже импортируете os из системы, но, расширяя мое выражение, вы можете импортировать все, что хотите, и использовать его. –

2

Другая возможность - посмотреть на Pyparsing, который является генератором общих парсеров. Он более мощный, чем вам нужно, но он может быть быстрее реализован.

+0

Вики-параграф (pyparsing.wikispaces.com) включает в себя пару примеров анализатора арифметических выражений - fourFn.py и simpleArith.py. Даже если вы не используете pyparsing, fourFn.py, скорее всего, будет разъяснять, как такой парсер реализует приоритет оператора. – PaulMcG

+0

Я просто понял, что OP хотел добавить других операторов. simpleArith.py показывает, как добавить факторный оператор (!) - evalArith.py (внизу страницы) расширяет simpleArith.py и показывает, как оценивать проанализированные значения. – PaulMcG