【问题标题】:Python Mathematical Formula computationPython数学公式计算
【发布时间】:2015-01-08 20:20:17
【问题描述】:

我正在编写一个 python 程序来计算公式。我读入了一个包含值、运算符和函数的字符串列表。

下面显示的代码接收一个字符串例如:

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

上面的代码是数学问题的后缀版本:power(2,3)+not(2=1) 程序应先计算 not(2=1),得到 1,然后计算 power(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 语句的问题;我不知道如何自动检查这些。谁能指出我正确的方向或协助我的代码?当我尝试检查“电源”时,它只是跳过了我的其余代码并尝试打印堆栈 - 这是空的导致错误。

【问题讨论】:

  • 你能发个MCVE吗?
  • @Christian 我不确定您还需要什么?我已经发布了复制问题时使用的代码。
  • 我认为他的意思是让您准确地确定哪些内容不适合您,以及您尝试过的内容 - 而不是发布您的整个脚本。
  • power(2,3)+not(2=1) 的后缀表示法不应该是2, 3, power, 2, 1, =, not, +吗?
  • 请检查并更正代码的缩进。另外,我倾向于不同意彼得的观点,即这不是正确的后缀。似乎有些运算符在之后,而有些则在它们各自的参数之前。也许这是唯一的问题?

标签: python formula


【解决方案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 代码中,一个函数实际上应该足以将所有需要的东西推送和弹出到堆栈中。为了实现基本实现,您可以简单地检查所有不同的操作员案例并执行任何需要的操作。如果提供的运算符都不匹配当前元素,您可以假设该元素是一个数值并简单地推送解析的浮点值。

请注意,这是一个非常快速和肮脏的实现,但它可能会引导您走上正确的轨道。

【讨论】:

    【解决方案2】:

    基于 IXI 的答案,您可以通过使用函数式编程来显着降低代码的复杂性和数量:创建从符号到要执行的操作的映射,然后只需在该映射的输入中查找符号。这样做,您会发现powernot 一点也不特别,而且可以轻松添加额外的一元和二元运算符。您甚至可以扩展它以支持三元运算符,例如 ... 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
    

    【讨论】:

      【解决方案3】:

      关于冗余细化的主题,这里是针对较少特殊情况的 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
      

      是的,我使用 Python 的 bool 类型是 int 的子类型,所以 True 实际上是 1。产生 9 还是 10 的区别仅来自幂参数的顺序(@ 987654325@ 或 3**2==9)。

      问题的根源在于您的原始输入表达式不是有效的后缀表示法,这使得评估顺序清晰,因此运算符优先级是多余的。如果not 出现在它的论点之前,你怎么知道什么时候评估它? not(1)、not(1==2) 和 not((1==2)+(3**2) 看起来都是可能的解释,对权力来说也好不到哪里去。

      【讨论】:

        猜你喜欢
        • 2022-07-04
        • 1970-01-01
        • 1970-01-01
        • 2022-07-25
        • 2015-02-25
        • 1970-01-01
        • 1970-01-01
        • 2014-03-09
        • 1970-01-01
        相关资源
        最近更新 更多