自己实现Python eval函数: Dijkstra的双栈算数表达式求值法

333 阅读1分钟

起源

《算法4th》中介绍了Java实现的“Dijkstra的双栈算数表达式求值法”, 让人想到python中的eval函数, 何不自己实现试试呢?

双栈算数表达式求值法

输入为(算子 算符 算子), 必须有括号, 简化思考和代码.

材料: 俩栈, 分别为a算子栈, b算符栈

a: 存储算子(数字)

b: 存储算符

忽略所有右括号(, 将输入字符串视为队列, 将字符依次出队, 遇到算子, 入a队, 遇到非()算符, 入b队. 遇到), 将a出栈俩元素(俩算子), b出栈一个元素(一个算符), 进行运算后结果压入a(参加下一轮运算). 当字符串为空时, 运算完毕, a中仅剩唯一一个算子, 即为最终结果.

具体参考《算法4th》 P80.

class Evaluate(object):
    def __init__(self, formula):
        self.ops = [] # 算子栈
        self.vals = [] # 算符栈

        if formula.strip() != "":
            for s in formula: # 在不支持字符串字符迭代的语言中, 应用队列实现
                if s == "(":
                    pass
                elif s == "+":
                    self.ops.append(s)
                elif s == "-":
                    self.ops.append(s)
                elif s == "*":
                    self.ops.append(s)
                elif s == "/":
                    self.ops.append(s)
                elif s == ")": # 计算括号内表达式
                    op = self.ops.pop()
                    v = self.vals.pop()
                    if op == "+":
                        v += self.vals.pop()
                    elif op == "-":
                        v = self.vals.pop() - v
                    elif op == "*":
                        v *= self.vals.pop()
                    elif op == "/":
                        v = self.vals.pop() / v
                    self.vals.append(v)
                else: # 非算符, 即算子, 则压入算子栈
                    self.vals.append(float(s))

        print(self.vals.pop())


evaluate = Evaluate("((3*4)+1)")

Output:

13