2012-03-13 8 views
22

Предположим, у меня есть стандартная строка Python (например, полученная от raw_input()), возможно, "2 + 2" для простоты.Математические операции из строки

Я хотел бы преобразовать эту строку в стандартные математические операции в Python, так что "2 + 2" вернется 4.

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

Нужно ли мне регулярное выражение?

+0

Это домашнее задание? Я думаю, вам придется писать парсер. Вы можете использовать некоторое итеративное или рекурсивное регулярное выражение для обработки парсеров и порядка операций, а затем просто проанализировать и линейно обработать все остальное. –

+0

Ха, я подумал, что кто-то собирается спросить об этом. Да, он занимается домашней работой, но это не то, что вы думаете. Понимаете, я пишу калькулятор геометрии/триггера, чтобы облегчить мою математическую жизнь. (См. Здесь: http: // stackoverflow.com/questions/9624515/basic-trig-math-atan-issue) Я полагаю, что если я достаточно хорошо понимаю проблему, чтобы написать программу, которая может понять это, мне не нужно делать эту работу вручную. :) –

+1

Также рассмотрим SimPy для символической математики. – Benjamin

ответ

32

Используйте функцию eval.

print eval('2 + 4') 

Выход:

6 

Вы даже можете использовать переменные или регулярный код питона.

a = 5 
print eval('a + 4') 

Выход:

9 

Вы также можете получить возвращаемые значения:

d = eval('4 + 5') 
print d 

Выход:

9 

Или вызов функции:

def add(a, b): 
    return a + b 

def subtract(a, b): 
    return a - b 

a = 20 
b = 10  
print eval('add(a, b)') 
print eval('subtract(a, b)') 

Выход:

30 
10 

В случае, если вы хотите написать парсер, может быть, вместо этого вы можете встроенный генератор кода Python, если это проще и использовать Eval для запуска кода. С помощью eval вы можете выполнить любую оценку Python.

С другой стороны, как уже отмечали другие, eval небезопасен, поэтому используйте его с умом.

+12

Да, будьте очень внимательны к людям, живущим в Эвале. Поскольку вопрос (для меня) подразумевает ввод от третьей стороны, вы должны знать, что это небезопасно. ИМО этот ответ должен был предупредить Big Fat об этом в начале. – pnovotnak

5

Самый простой способ заключается в использовании eval как в:

>>> eval("2 + 2") 
4 

Обратите внимание на тот факт, я включил пробелы в строке. eval будет выполнять строку, как если бы это был код Python, поэтому, если вы хотите, чтобы вход был в синтаксисе, отличном от Python, вы должны разобрать строку самостоятельно и вычислить, например, eval("2x7") не даст вам 14, потому что Python использует * для умножения, а не x.

+0

Будет ли 'eval()' позаботиться о круглых скобках, порядке операций и обо всем этом джазе? –

+1

Да, это так, он использует те же правила, что использует Python. –

7

Regex не очень поможет. Прежде всего, вам нужно будет учесть приоритет операторов, а во-вторых, вам нужно работать с круглыми скобками, что невозможно с регулярным выражением.

В зависимости от того, какое именно выражение вам необходимо проанализировать, вы можете попробовать либо Python AST, либо (скорее всего) pyparsing. Но, прежде всего, я бы рекомендовал прочитать что-то о syntax analysis в целом и Shunting yard algorithm в частности.

И бороться с соблазном использования eval, это небезопасно.

+0

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

+0

Чтение синтаксического анализа и построение собственного анализатора может быть чрезмерным, чтобы решить его проблему. – hochl

+1

Если ваша цель состоит в том, чтобы «знать математику достаточно хорошо, чтобы оправдать это не вручную», используя 'eval()', чтобы сделать все это автоматически для вас, точно не соответствует вашим целям. –

3

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

import re 
s = raw_input('What is your math problem? ') 
if re.findall('\d+? *?\+ *?\d+?', s): 
    print eval(s) 
else: 
    print "Try entering a math problem" 

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

+0

Вы можете сопоставить пробелы с '\ s' ... – hochl

4

автор вопроса прокомментировал:

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

Если он пишет математическое выражение в качестве учебного упражнения, использование eval() не поможет. Плюс это ужасный дизайн.

Вы можете использовать калькулятор, используя Reverse Polish Notation вместо стандартной математической нотации. Это значительно упрощает синтаксический анализ. Это все равно будет хорошим упражнением

+0

Вещь - это не учебное упражнение. Это ах, избыточно-выпрямитель. И работа, которую я хотел бы устранить, является избыточной, потому что я уже знаю ее. ;) –

+0

Но вызов 'eval (выражение)' не означает, что вы «хорошо понимаете проблему достаточно, чтобы написать программу». Это означает, что входной парсер Python понимает проблему. – japreiss

+0

Ну, я немного отстаю от стандартных уравнений, умножения и деления. Входной парсер Python не будет понимать проблемы, над которыми я сейчас работаю. Действительно, нет возможности даже ввести их в стандартную консоль. :) –

5

Если вы хотите, чтобы сделать это безопасно, вы можете использовать http://docs.python.org/library/ast.html#ast.literal_eval

из этого ответа: Python "safe" eval (string to bool/int/float/None/string)

Это не может сделать математику, но можно разобрать математические операторы, а затем работают на безопасно оцененных условиях.

2

Лучше всего было бы сделать:

print eval("2 + 2")

Если вы хотите, чтобы вы могли использовать переменную:

addition = eval("2 + 2") print addition

Если вы действительно хотите, вы могли бы использовать функции:

def add(num1, num2): eval("num1 + num2")

4

Вы можете использовать эту функцию, которая выполняет те же функции, что и функция eval(), но простым способом, используя функцию.

def numeric(equation): 
    if '+' in equation: 
     y = equation.split('+') 
     x = int(y[0])+int(y[1]) 
    elif '-' in equation: 
     y = equation.split('-') 
     x = int(y[0])-int(y[1]) 
    return x 
+0

просто нужно вызвать функцию в любом месте, где бы вы ни хотели. –

Смежные вопросы