实现一个简单四则运算解析器:从零开始解析表达式
题目背景:四则运算的挑战
最近在刷题时遇到了一道有趣的编程题——实现一个基本计算器。题目要求我们解析一个字符串形式的数学表达式并计算其结果。表达式包含加减乘除、括号以及数字,最终需要返回整数结果。此外,还明确要求不能借助内置的 eval 函数,而是从头实现解析逻辑。
题目要求
给定一个字符串 expression,如 "3+4*5/(3+2)",需要返回其计算结果。题目示例如下:
输入:expression = "3+4*5/(3+2)"
输出:7
问题分析
这道题的难点在于需要自己实现运算优先级的处理:
- 加减法和乘除法优先级不同。
- 括号改变了优先级,需要优先计算括号内的表达式。
- 实现过程中需要正确解析字符串,并依次计算中间结果。
为了解决这些问题,我们需要分步构造计算器的逻辑。
解题思路:构造一个递归解析器
面对如此复杂的运算优先级,可以借助递归方法来逐层解析括号内容:
- 分层解析:外层负责处理加减法,遇到括号时递归调用内部表达式解析器。
- 局部计算:在同一级别中,先将乘除法优先处理,再处理加减法。
- 栈模拟计算过程:用栈存储中间结果,将高优先级的计算直接压入栈中。
以下是实现的核心步骤:
- 从左到右解析字符串,分割出数字和操作符。
- 当遇到括号时递归处理括号内部表达式。
- 将最终的中间结果合并,返回计算结果。
代码实现
以下是用 Python 实现的完整代码:
def calculate(expression: str) -> int:
def helper(s: list) -> int:
stack = []
num = 0
sign = '+'
while len(s) > 0:
char = s.pop(0)
if char.isdigit():
num = num * 10 + int(char)
if char == '(':
num = helper(s)
if char in "+-*/)" or len(s) == 0:
if sign == '+':
stack.append(num)
elif sign == '-':
stack.append(-num)
elif sign == '*':
stack.append(stack.pop() * num)
elif sign == '/':
stack.append(int(stack.pop() / num))
sign = char
num = 0
if char == ')':
break
return sum(stack)
return helper(list(expression))
测试与验证
用一些测试用例来验证代码是否正确:
# 示例 1
print(calculate("1+1")) # 输出:2
# 示例 2
print(calculate("3+4*5/(3+2)")) # 输出:7
# 示例 3
print(calculate("4*2*5-2/1")) # 输出:12
# 示例 4
print(calculate("(1+(4+5+2)-3)+(6+8)")) # 输出:23
# 示例 5
print(calculate("2*(5+5*2)/3+(6+8*3)")) # 输出:40
通过测试可以发现,代码能正确解析表达式并返回期望的结果。
实现过程中的坑点与优化
- 整数除法处理:Python 的除法会返回浮点数,但题目要求返回整数,因此需要用
int()强制转换。 - 多位数字解析:注意从字符串中连续读取多位数字,避免只解析个位。
- 括号嵌套问题:递归时需要正确处理多层括号的结束条件。
我的收获与心得
这道题让我充分理解了递归的强大之处。通过递归分层解析表达式,我们可以清晰地处理括号和优先级问题。用栈模拟计算过程,也让我对“分而治之”的思想有了更深刻的认识。
此外,借助这道题,我还学会了如何一步步将复杂问题拆解为可管理的小模块。每次完成一个小模块并验证正确性,能让整个程序的开发更加顺畅。
写在最后
如果你和我一样,是个后端开发者,可能觉得“计算器”这类题和日常业务需求关系不大。但通过这样的题目,我们可以锻炼对算法和数据结构的掌握程度,同时也能在复杂问题面前学会冷静分析、层层拆解。
有时候,刷题不仅是为了提升编程技能,更是一次提升逻辑思维的机会。如果你也对这道题感兴趣,不妨尝试一下!