2015-01-08 5 views
1

Я пишу программу python для вычисления формулы. Я читаю в списке строк, которые содержат значения, операторы и функции.Расчет математической формулы Python

Код, показанный ниже, получает строку, например:

['not', 1.0, 2.0, '=', 'power', 2.0, 3.0, '+'] 

Код выше, является вариант постфикса математической задачи: Мощность (2,3) + (не 2 = 1) программа должна вычислить нет (2 = 1) во-первых, в результате чего в 1, а затем рассчитать мощность (2,3) дает 9, а затем 8 + 0 приводит к возвращению 8.

до сих пор мой код, чтобы вычислить ответы

stack = [] 
    def calculate(inputs): 
     if (inputs[0] == "sum"): 
     inputs.remove("sum") 
    for a in inputs: 
     if (a) == "not": 
      inputs.remove(a) 
      op1, op2 = inputs[0], inputs[1] 
      inputs.remove(op1) 
      inputs.remove(op2) 
      if op1 != op2: 
       stack.append('0') 
      else: 
       stack.append('1') 
      continue 
     if (a) == 'power': 
      inputs.remove(a) 
      continue  
     if type(a) is float: 
      stack.append(a) 
      continue 
     op1, op2 = stack.pop(), stack.pop() 
     #if a == 'power': 

     if a == '+': 
      stack.append(op2 + op1) 
     elif a == '-': 
      stack.append(op1 - op2) 
     elif a == '*': 
      stack.append(op2 * op1) 
     elif a == '/': 
      stack.append(op1/op2) 
     elif a == '=': 
      if op1 != op2: 
       stack.append('0') 
      else: 
       stack.append('1') 


    if (len(stack) > 1): 
     lenStack = len(stack)-1 
     for x in range(0, lenStack): 
      stack.append('+') 
     stack.append(_calcSum(stack)) 
    return stack.pop() 

def _calcSum(stack): 
    newStack = [] 
    for a in stack: 
     if type(a) is float: 
      newStack.append(a) 
      continue 
     op1, op2 = newStack.pop(), newStack.pop() 
     if a == '+': 
      newStack.append(op2 + op1) 
     elif a == '-': 
      newStack.append(op1 - op2) 
     elif a == '*': 
      newStack.append(op2 * op1) 
     elif a == '/': 
      newStack.append(op1/op2) 
    return newStack.pop() 

Однако у меня возникают проблемы с утверждением NOT и POWER; Я не могу понять, как автоматически проверять их. Может ли кто-нибудь указать мне в правильном направлении или помочь с моим кодом? Когда я пытаюсь проверить «власть», он просто пропускает остальную часть моего кода и пытается распечатать стек, который пуст, вызывая ошибку.

+0

Не могли бы вы опубликовать [ MCVE] (http://stackoverflow.com/help/mcve)? – Christian

+0

@Christian Я не уверен, что еще вам нужно? Я опубликовал код, который используется при репликации моей проблемы. – Craig

+0

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

ответ

1

Я думаю, что следующий код может быть то, что вы хотите:

import math 

test_input = ['2', '1', '=', 'not', '2', '3', 'power', '+'] 

def calculate(input): 
    newStack = [] 
    for a in input: 
     print newStack 

     if a == '+': 
      op1, op2 = newStack.pop(), newStack.pop() 
      newStack.append(op2 + op1) 
     elif a == '-': 
      op1, op2 = newStack.pop(), newStack.pop() 
      newStack.append(op1 - op2) 
     elif a == '*': 
      op1, op2 = newStack.pop(), newStack.pop() 
      newStack.append(op2 * op1) 
     elif a == '/': 
      op1, op2 = newStack.pop(), newStack.pop() 
      newStack.append(op1/op2) 
     elif a == '=': 
      op1, op2 = newStack.pop(), newStack.pop() 
      if op1 == op2: 
       newStack.append(1) 
      else: 
       newStack.append(0) 
     elif a == 'not': 
      op = newStack.pop() 
      if op > 0: 
       newStack.append(0) 
      else: 
       newStack.append(1) 
     elif a == 'power': 
      op1, op2 = newStack.pop(), newStack.pop() 
      newStack.append(math.pow(op1, op2)) 
     else: 
      newStack.append(float(a)) 

    return newStack.pop() 

Как PeterE отметил в своем комментарии код постфикса неправильно. Я предполагаю, что ваш желаемый постфиксный код, вероятно, равен 2 1 = not 2 3 power +. Также обратите внимание, что тогда конечное значение будет 9+1 = 10, а не 8+0 = 8.

В Википедии есть хорошая страница для постфиксного кода: http://en.wikipedia.org/wiki/Reverse_Polish_notation.

В коде python одной функции на самом деле должно быть достаточно, чтобы нажать и поместить все необходимые вещи в стек. Чтобы выполнить базовую реализацию, вы можете просто проверить все свои операционные случаи и выполнить любые необходимые операции. Если ни один из предоставленных операторов не соответствует текущему элементу, вы можете предположить, что этот элемент является числовым значением и просто выталкивает значение parsed float.

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

1

Основываясь на ответе IXI, вы можете значительно уменьшить сложность и количество кода, используя функциональное программирование: создать сопоставление от символов к выполняемым операциям, а затем просто просмотреть символы на входе в этом сопоставлении , Сделав это, вы увидите, что power и not не являются особыми, и дополнительные унарные и двоичные операторы могут быть добавлены с легкостью. Вы могли бы даже расширить его для поддержки тройных операторов, таких как ... if ... else ... (хотя вам придется писать их в постфиксной форме).

BIN_OP = {"+": lambda x, y: x + y, 
      "-": lambda x, y: x - y, 
      "*": lambda x, y: x * y, 
      "/": lambda x, y: x/y, 
      "power": lambda x, y: x**y, 
      "=": lambda x, y: int(x == y)} 
UN_OP = {"not": lambda x: int(not x)} 

def calculate(tokens): 
    stack = [] 
    for token in tokens: 
     if token in BIN_OP: 
      op1, op2 = stack.pop(), stack.pop() 
      operation = BIN_OP[token] 
      stack.append(operation(op1, op2)) 
     elif token in UN_OP: 
      op1 = stack.pop() 
      operation = UN_OP[token] 
      stack.append(operation(op1)) 
     else: 
      stack.append(float(token)) 
    return stack.pop() 

Пример:

>>> calculate(['2', '1', '=', 'not', '2', '3', 'power', '+']) 
10.0 
1

На тему избыточной изысканности, вот вариант решения tobias_k по реструктуризации для меньшего числа особых случаев:

from operator import add, sub, mul, truediv, pow, eq, not_ 

ops = {"+": add, "-": sub, "*": mul, "/": truediv, 
     "power": pow, "=": eq, "not": not_} 
# Mark how many inputs are needed 
ops = {k:(1 if f is not_ else 2, f) for (k,f) in ops.items()} 

def calculate(tokens): 
    stack = [] 
    for token in tokens: 
     try: 
      args,func = ops[token] 
      stack[-args:] = [func(*stack[-args:])] 
     except KeyError: 
      stack.append(float(token)) 
    return float(stack[-1]) 

Пример:

>>> calculate("2 1 = not 2 3 power +".split()) 
9.0 
>>> calculate("2 1 = not".split()) 
1.0 
>>> calculate("2 3 power".split()) 
8.0 

Да, я использую tha t Тип bool Python - это подтип int, поэтому True действительно 1.Разница в том, следует ли производить 9 или 10, происходит просто из порядка аргументов мощности (2**3==8 или 3**2==9).

Корень проблемы остается в том, что исходное исходное выражение не является допустимым постфиксным обозначением, что делает порядок оценки четким и, следовательно, избыточным приоритетом оператора. Если not подходит к аргументу, как вы можете определить, когда его оценивать? не (1), не (1 == 2), а не ((1 == 2) + (3 ** 2) все выглядят как возможные интерпретации, и это не лучше для власти.

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