使用python编程简单四则计算器

137 阅读5分钟

问题描述

小F面临一个编程挑战:实现一个基本的计算器来计算简单的字符串表达式的值。该字符串表达式有效,并可能包含数字(0-9)、运算符(+,-,*,/)及括号(())。注意,字符串中不包含空格。除法运算应只保留整数结果。请实现一个解析器计算这些表达式的值,且不使用任何内置的eval函数。

代码实现思路

第一次自己写题解,本身水平也有限...还只在写较简单题的阶段,还望海涵

首先,我们需要解析输入的字符串表达式,识别其中的数字、运算符和括号,并按顺序进行计算。这涉及到几个关键步骤:

  1. 初始化两个栈:num_stack 用于存储数字,op_stack 用于存储操作符。

  2. 遍历表达式字符串,对于每个字符,根据其类型(数字、运算符、括号)进行不同的处理:

    • 数字直接压入 num_stack
    • 操作符需要根据其优先级和栈顶操作符的优先级进行处理。
    • 左括号直接压入 op_stack
    • 右括号则触发括号内表达式的计算,直到遇到左括号为止。
  3. 最后处理栈中剩余的操作符,得到最终计算结果。

代码详细说明

以下是代码的详细实现及其解释:

python

def solution(expression):
    num_stack = []
    op_stack = []
    
    i = 0
    while i < len(expression):
        char = expression[i]
        
        if char.isdigit():
            # 处理数字
            num = int(char)
            num_stack.append(num)
        
        elif char in "+-*/":
            # 处理操作符
            while op_stack and should_calculate_before(op_stack[-1], char):
                calculate(num_stack, op_stack)
            op_stack.append(char)
        
        elif char == '(':
            # 处理左括号
            op_stack.append(char)
        
        elif char == ')':
            # 处理右括号
            while op_stack and op_stack[-1] != '(':
                calculate(num_stack, op_stack)
            op_stack.pop()  # 弹出左括号
        
        i += 1
    
    # 处理剩余的操作符
    while op_stack:
        calculate(num_stack, op_stack)
    
    return num_stack[0]

def should_calculate_before(op1, op2):
    # 判断op1是否应该在op2之前计算
    # 例如,乘除优先级高于加减
    if op1 in "*/" and op2 in "+-":
        return True
    if op1 in "+-" and op2 in "*/":
        return False
    return False

def calculate(num_stack, op_stack):
    # 从栈中弹出操作数和操作符进行计算
    op = op_stack.pop()
    num2 = num_stack.pop()
    num1 = num_stack.pop()
    
    if op == '+':
        result = num1 + num2
    elif op == '-':
        result = num1 - num2
    elif op == '*':
        result = num1 * num2
    elif op == '/':
        result = num1 // num2  # 只保留整数结果
    
    num_stack.append(result)

if __name__ == "__main__":
    #  You can add more test cases here
    print(solution("1+1") == 2)
    print(solution("3+4*5/(3+2)") == 7)
    print(solution("4+2*5-2/1") == 12)
    print(solution("(1+(4+5+2)-3)+(6+8)") == 23)

代码思路与过程

  1. 初始化和循环处理

    首先,我们初始化两个栈:num_stack 用于存储数字,op_stack 用于存储操作符。这两个栈将帮助我们处理计算的优先级和括号嵌套。

    python

    num_stack = []
    op_stack = []
    

    接下来,我们使用一个 while 循环遍历整个表达式字符串。每次循环读取一个字符,并根据该字符的类型(数字、操作符、括号)进行不同的处理。

    python

    i = 0
    while i < len(expression):
        char = expression[i]
    
  2. 处理数字

    如果当前字符是数字,我们需要将其转换为整数并压入 num_stack。在我们的例子中,每次读取的字符都是单个数字,因此可以直接转换。对于多位数的情况,需要进一步处理,但这里假设每个数字字符都是有效的单个数字。

    python

    if char.isdigit():
        num = int(char)
        num_stack.append(num)
    
  3. 处理操作符

    如果当前字符是操作符(+、-、*、/),我们需要考虑操作符的优先级。如果当前操作符的优先级低于或等于栈顶操作符的优先级,我们需要先处理栈顶操作符。

    python

    elif char in "+-*/":
        while op_stack and should_calculate_before(op_stack[-1], char):
            calculate(num_stack, op_stack)
        op_stack.append(char)
    

    这里我们使用了一个辅助函数 should_calculate_before(op1, op2) 来判断操作符的优先级:

    python

    def should_calculate_before(op1, op2):
        if op1 in "*/" and op2 in "+-":
            return True
        if op1 in "+-" and op2 in "*/":
            return False
        return False
    

    该函数判断 op1 是否应该在 op2 之前计算,例如,乘除操作符的优先级高于加减操作符。

  4. 处理括号

    左括号直接压入 op_stack,而右括号则表示一个子表达式的结束,我们需要计算括号内的表达式。为此,我们不断从栈中弹出操作符和操作数进行计算,直到遇到左括号。

    python

    elif char == '(':
        op_stack.append(char)
    elif char == ')':
        while op_stack and op_stack[-1] != '(':
            calculate(num_stack, op_stack)
        op_stack.pop()  # 弹出左括号
    
  5. 处理剩余的操作符

    当整个表达式遍历完后,可能还有一些操作符留在 op_stack 中,我们需要逐一处理它们。

    python

    while op_stack:
        calculate(num_stack, op_stack)
    
  6. 计算函数

    计算函数 calculate(num_stack, op_stack) 从栈中弹出两个操作数和一个操作符进行计算,并将结果压入 num_stack

    python

    def calculate(num_stack, op_stack):
        op = op_stack.pop()
        num2 = num_stack.pop()
        num1 = num_stack.pop()
        
        if op == '+':
            result = num1 + num2
        elif op == '-':
            result = num1 - num2
        elif op == '*':
            result = num1 * num2
        elif op == '/':
            result = num1 // num2  # 只保留整数结果
        
        num_stack.append(result)
    

总结

通过上述代码,实现了一个基本的计算器,可以解析和计算包含数字、运算符和括号的字符串表达式。我使用了两个栈来处理操作符的优先级和括号嵌套,通过递归地计算表达式的值,通过解析和计算实现了这一功能。希望这个详细的描述能帮助你更好地理解。