我正在编写一个python程序来计算公式。我读了一个包含值,运算符和函数的字符串列表。
下面显示的代码接收一个字符串,例如:
['not', 1.0, 2.0, '=', 'power', 2.0, 3.0, '+']
上面的代码是数学问题的后缀版本:power(2,3)+ not(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语句的问题;我无法弄清楚如何自动检查这些。任何人都可能指出我正确的方向或协助我的代码?当我尝试检查'power'时,它只是跳过我剩下的代码并尝试打印堆栈 - 这是空的,导致错误。
答案 0 :(得分: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代码中,一个函数实际上应该足以将所有需要的东西推送到堆栈。要实现基本实现,您可以简单地检查所有不同的操作员案例并执行任何所需的操作。如果所提供的运算符都不匹配当前元素,则可以假设该元素是一个数值,只需按下已解析的float值。
请注意,这是一个非常快速和肮脏的实现,但它可能会引导您走上正确的轨道。
答案 1 :(得分: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
答案 2 :(得分: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
是的,我使用Python的bool
类型是int
的子类型,所以True实际上是1.生成9或10的区别是只需从权力参数的顺序(2**3==8
或3**2==9
)。
问题的根源仍然是您的原始输入表达式不是有效的后缀表示法,这使得评估顺序清晰,因此运算符优先级是多余的。如果not
出现在它的论证之前,你怎么知道何时进行评估呢?不是(1),不是(1 == 2),而不是((1 == 2)+(3 ** 2)看起来都像是可能的解释,而且对权力没有好处。