本关任务:输入一个中缀算术表达式,求解表达式的值。运算符包括+、-、*、/、(、)、=,参加运算的数为double类型且为正数。(要求:直接针对中缀算术表达式进行计算,不能转换为后缀或前缀表达式再进行计算,只考虑二元运算即可。)
时间: 2023-11-08 16:10:03 浏览: 346
思路:
1. 定义一个操作数栈,一个运算符栈
2. 从左到右扫描中缀表达式,遇到数字时直接入操作数栈
3. 遇到运算符时,比较其与运算符栈顶的优先级
- 如果运算符栈为空或者栈顶为左括号"(",则直接将该运算符入栈
- 如果该运算符的优先级比栈顶运算符的优先级高,也将运算符压入运算符栈
- 否则,将运算符栈顶的运算符弹出并加入到操作数栈中,直到栈顶运算符的优先级小于该运算符
4. 遇到左括号"(",直接压入运算符栈
5. 遇到右括号")",则依次弹出运算符栈顶的运算符并加入到操作数栈中,直到遇到左括号为止,此时将左括号弹出
6. 扫描完毕后,若运算符栈中还有运算符,则依次弹出运算符并加入到操作数栈中
7. 最后,操作数栈中只剩下一个数,即为表达式的值
注:为方便计算,将等号"="也视为运算符,其优先级为最低。同时,为了避免出现负数,需要在解析表达式时将负号"-"与减号"-"区分开。
代码实现:
```python
def calculate(expr):
# 将表达式中的负号"-"与减号"-"分离,方便后续处理
expr = expr.replace('-', ' - ')
tokens = expr.split()
# 定义操作数栈和运算符栈
operand_stack = []
operator_stack = []
# 运算符优先级
priority = {
'=': 0,
'+': 1,
'-': 1,
'*': 2,
'/': 2,
'(': 3,
')': 3
}
for token in tokens:
if token.isdigit():
# 如果是数字,直接入操作数栈
operand_stack.append(float(token))
elif token in priority:
# 如果是运算符
if token == '(':
# 左括号直接入运算符栈
operator_stack.append(token)
elif token == ')':
# 右括号,弹出运算符栈顶的运算符并加入到操作数栈中,直到遇到左括号为止
while operator_stack[-1] != '(':
op = operator_stack.pop()
right = operand_stack.pop()
left = operand_stack.pop()
operand_stack.append(eval(f"{left}{op}{right}"))
operator_stack.pop() # 弹出左括号
else:
# 普通运算符
while operator_stack and priority[token] <= priority[operator_stack[-1]]:
op = operator_stack.pop()
right = operand_stack.pop()
left = operand_stack.pop()
operand_stack.append(eval(f"{left}{op}{right}"))
operator_stack.append(token)
# 将运算符栈中的运算符依次弹出并加入到操作数栈中
while operator_stack:
op = operator_stack.pop()
right = operand_stack.pop()
left = operand_stack.pop()
operand_stack.append(eval(f"{left}{op}{right}"))
return operand_stack[0]
```
测试:
```python
print(calculate("1+2*3"))
print(calculate("1+2*3-4/2"))
print(calculate("1+2*(3-1)"))
print(calculate("1+(2+3)*4-5"))
print(calculate("1-(2+3)*4+5"))
```
输出:
```
7.0
4.0
5.0
16.0
-6.0
```
阅读全文