首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python数学公式计算

Python数学公式计算
EN

Stack Overflow用户
提问于 2015-01-09 04:20:17
回答 3查看 195关注 0票数 1

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

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

代码语言:javascript
复制
['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。

到目前为止,我计算答案的代码

代码语言:javascript
复制
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语句时遇到了问题;我不知道如何自动检查这些语句。有没有人可以给我指出正确的方向,或者帮助我编写代码?当我尝试检查“power”时,它只是跳过我的其余代码,并尝试打印堆栈-它是空的,从而导致错误。

EN

回答 3

Stack Overflow用户

发布于 2015-01-09 05:02:29

我认为下面的代码可能是您想要的:

代码语言:javascript
复制
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代码中,一个函数实际上应该足以将所有需要的东西推送和弹出到堆栈上。要实现基本的实现,您可以简单地检查所有不同的运算符情况,并执行任何需要的操作。如果提供的运算符都不与当前元素匹配,则可以假定该元素是一个数值,并简单地推送解析后的浮点值。

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

票数 1
EN

Stack Overflow用户

发布于 2015-01-09 18:14:52

基于IXI的答案,您可以通过使用函数式编程显著降低复杂性和代码量:创建从符号到要执行的操作的映射,然后在该映射中查找输入中的符号。这样做,您将看到powernot一点也不特殊,并且可以很容易地添加额外的一元和二元运算符。您甚至可以扩展它以支持三元运算符,例如... if ... else ... (尽管您必须以后缀的形式编写它们)。

代码语言:javascript
复制
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()

示例:

代码语言:javascript
复制
>>> calculate(['2', '1', '=', 'not', '2', '3', 'power', '+'])
10.0
票数 1
EN

Stack Overflow用户

发布于 2015-01-09 20:33:44

关于冗余精化的主题,这里是tobias_k的解决方案的一个变体,它针对更少的特殊情况进行了重构:

代码语言:javascript
复制
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])

示例:

代码语言:javascript
复制
>>> 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的区别仅仅来自于幂参数的顺序(2**3==83**2==9)。

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27848840

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档