用栈解析算术表达式[Python版]

代码中采用了三步实现算术表达式的解析:

1. 将算术表达式(字符串)转换成一个列表parseElement方法

2. 将列表表示的算术表达式转换成后缀表达式changeToSuffix

3. 计算后缀表达式的结果

这里我是为了方便, 就写了个parseElement, 不想那方法写到后面却把自己绕住了, 可以想象一个带自增, 位, 逻辑, 算术的表达式的数值提取是多么的复杂...

parseElement自己感觉是一个比较失败的方法, 所以从一个普遍的角度来分析以下算术表达式的解析:

以(A + B) * C / D ** E + F * G为例

第一部分: 将中缀表达式(上面就是, 具体去查有关前缀, 中缀, 后缀表达式)

这一步需要一个栈用来保存运算符, 一个字符串用来保存输出的后缀表达式

符号栈: signStack

后缀表达式: result

过程: 读取表达式中每个元素(数字或运算符, 我的parseElement意在解决这个问题, 却做的不成功)

原则:

1. 操作数直接输出到result

2. (直接进栈

3. )出栈直到遇到一个"("(注意: 这里"("必须出栈), 中间出栈的元素按出栈顺序输出到result

4. 其他运算符, 检查栈顶元素, 如果栈顶比当前运算符优先级高或相同(优先级相同, 按顺序执行)则先将栈顶出栈, 再入栈. 如果当前元素优先级高, 则直接入栈.

操作过程的状态变化

signStack |result |current char

------------------------------------------------------

( | |(

( |A |A

(, + | |+

( |AB |B

|AB+ |)

* | |*

* |AB+C |C

/ |AB+C* |/

/ |AB+C*D |D

/, **|AB+C*D |**

/, **|AB+C*DE |E

+|AB+C*DE**/ |+

+|AB+C*DE**/F |F

+, * |AB+C*DE**/F |*

|AB+C*DE**/FG*+ |G

唉, 不太美观啊..

第二部分: 计算后缀表达式(AB+C*DE**/FG*+)

这一步需要一个栈用来保存操作数

值栈

过程: 读取后缀表达式中每个元素

原则:

1. 操作数直接进栈

2. 遇到一个运算符则出栈两个, 计算结果再进栈

操作过程的状态变化

stack |current char

------------------------------------------------------

A |A

A, B |B

(A+B) |+

(A+B), C |C

(A+B)*C |*

((A+B)*C), D |D

((A+B)*C), D, E |E

((A+B)*C), (D**E) |**

(((A+B)*C)/(D**E))|/

(((A+B)*C)/(D**E)), F |F

(((A+B)*C)/(D**E)), F, G |G

(((A+B)*C)/(D**E)), (F*G) |*

((((A+B)*C)/(D**E))+(F*G)) |+

还是不很美观哈, 呵呵, 逗号把元素隔开, 应该还是可以看的比较清晰了...呵呵..

''' Created on 2009-9-4 @author: selfimpr ''' signable = ["+", "-", "*", "/", "%", "(", ")"] numberable = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "."] signs = ["+", "-", "*", "/", "%", "**", "//"] priorities = {"(": 9, ")": 9, "**": 7, "*": 5, "/": 5, "%": 5, "//": 5, "+": 3, "-": 3} class Stack(object): ''' author: selfimpr blog: http://blog.csdn.net/lgg201 mail: lgg860911@yahoo.com.cn company: http://www.dartfar.com function: This is a general stack, use to do the sign and number's temp store ''' def __init__(self): self.datas = [] def push(self, data): self.datas.append(data) def pop(self): return self.datas.pop() def peek(self): if self.datas: return self.datas[len(self.datas) - 1] def size(self): return len(self.datas) def empty(self): return len(self.datas) < 1 #a bit function, return last element of list def getLast(l): if l: return l[len(l) - 1] def parseElement(expression): ''' author: selfimpr blog: http://blog.csdn.net/lgg201 mail: lgg860911@yahoo.com.cn company: http://www.dartfar.com function: parse a string expression to list ''' result = [] cur = "" for index in range(len(expression)): ch = expression[index] if numberable.__contains__(ch): cur += ch elif signable.__contains__(ch): if cur: result.append(float(cur)) cur = "" if ["*", "/"].__contains__(ch) and getLast(result) == ch: result[len(result) - 1] *= 2 elif ["+", "-"].__contains__(ch) / and ["+", "-", "*", "/", "%", "**", "//", "(", ")"].__contains__(getLast(result)) / and not ["+", "-", "*", "/", "%", "**", "//", "(", ")"].__contains__(expression[index + 1]): cur += ch else: result.append(ch) else: raise Exception, "Error" if cur: result.append(float(cur)) return result def priority(sign1, sign2): ''' author: selfimpr blog: http://blog.csdn.net/lgg201 mail: lgg860911@yahoo.com.cn company: http://www.dartfar.com function: check priority between two arguments ''' return priorities[sign1] > priorities[sign2] def changeToSuffix(expression): ''' author: selfimpr blog: http://blog.csdn.net/lgg201 mail: lgg860911@yahoo.com.cn company: http://www.dartfar.com function: change a infix expression to suffix (Notice: the infix is a list, you can parse a infix expression to list by previous function names parseElement) ''' if not isinstance(expression, list) or not list or isinstance(expression[0], list): raise Exception("expression must be a not-null list and first element must be a number") suffix = [] signStack = Stack() for element in expression: if isinstance(element, float): suffix.append(element) elif ["+", "-", "*", "/", "%", "**", "//", "(", ")"].__contains__(element): if element == "(": signStack.push(element) elif element == ")": while not signStack.empty()/ and signStack.peek() != "(": suffix.append(signStack.pop()) signStack.pop() else: while not signStack.empty()/ and not priority(element, signStack.peek()): if signStack.peek() == "(": break suffix.append(signStack.pop()) signStack.push(element) else: raise Exception("Unsupport sign or number") while not signStack.empty(): suffix.append(signStack.pop()) return suffix def calc(a, b, sign): ''' author: selfimpr blog: http://blog.csdn.net/lgg201 mail: lgg860911@yahoo.com.cn company: http://www.dartfar.com function: calculate result a sign b ''' if sign == "+": return b + a elif sign == "-": return b - a elif sign == "*": return b * a elif sign == "/": return b / a elif sign == "**": return b ** a elif sign == "//": return b // a else: raise Exception("Unsupport sign: %s" % sign) def account(expression): ''' author: selfimpr blog: http://blog.csdn.net/lgg201 mail: lgg860911@yahoo.com.cn company: http://www.dartfar.com function: calculate a suffix expression (Notice: it must a list) ''' if not isinstance(expression, list) or not list or isinstance(expression[0], list): raise Exception("expression must be a not-null list and first element must be a number") numberStack = Stack() for element in expression: if isinstance(element, float): numberStack.push(element) else: numberStack.push(calc(numberStack.pop(), numberStack.pop(), element)) return numberStack.pop()

好的,我可以帮您解析一个中缀算术表达式并计算其结果。首先需要将中缀表达式转换为后缀表达式,然后利用栈的特性进行计算。 具体步骤如下: 1. 创建一个和一个空列表作为结果集。 2. 遍历表达式中的每一个字符。 3. 如果字符是数字,将其添加到结果列表中。 4. 如果字符是左括号'(',将其压入中。 5. 如果字符是右括号')',则弹出中的所有运算符,直到遇到左括号为止,并将运算符添加到结果列表中。 6. 如果字符是运算符,将该运算符与顶运算符比较: a. 如果为空,将该运算符压入中。 b. 如果该运算符优先级大于顶运算符,将其压入中。 c. 如果该运算符优先级小于或等于顶运算符,将顶运算符弹出并添加到结果列表中,重复步骤6直到满足条件b。 7. 如果遍历完了表达式,而中还有运算符,将其弹出并添加到结果列表中。 8. 根据后缀表达式,依次弹出运算数并进行计算,最终得到表达式的值。 下面是一个Python实现: ```python # 定义运算符优先级 priority = {'+':1, '-':1, '*':2, '/':2, '(':0, ')':0} # 将中缀表达式转换为后缀表达式 def infix_to_postfix(expression): result = [] # 结果列表 stack = [] # 运算符 # 遍历表达式 for char in expression: # 如果是数字,添加到结果列表 if char.isdigit(): result.append(char) # 如果是左括号,压入中 elif char == '(': stack.append(char) # 如果是右括号,弹出中的运算符,并将其添加到结果列表中,直到遇到左括号 elif char == ')': while stack and stack[-1] != '(': result.append(stack.pop()) stack.pop() # 弹出左括号 # 如果是运算符,比较其与顶运算符的优先级 elif char in ['+', '-', '*', '/']: while stack and priority[char] <= priority[stack[-1]]: result.append(stack.pop()) stack.append(char) else: pass # 忽略=号 # 遍历结束后,弹出中剩余的运算符 while stack: result.append(stack.pop()) return result # 根据后缀表达式计算表达式的值 def calculate(postfix_expression): stack = [] # 运算数 # 遍历后缀表达式 for char in postfix_expression: if char.isdigit(): stack.append(int(char)) else: b = stack.pop() a = stack.pop() if char == '+': result = a + b elif char == '-': result = a - b elif char == '*': result = a * b elif char == '/': result = a / b stack.append(result) return stack[0] # 测试 expression = input("请输入中缀表达式:") postfix_expression = infix_to_postfix(expression) result = calculate(postfix_expression) print("表达式的值为:", result) ``` 例如,输入表达式"3 * (1 + 4) / 2 = ",程序会输出"表达式的值为: 7.5"。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值