You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

新手求助:如何为自定义计算器添加多嵌套括号支持?

给新手的计算器括号支持实现方案

核心思路

用递归处理括号是最容易理解的方式:括号是嵌套结构,遇到左括号(时,就递归计算括号内的完整表达式,直到找到对应的右括号),把括号内的计算结果替换掉整个括号部分,再继续处理剩下的表达式。

修改后的完整代码

def parse_expression(expr, calculate_func):
    elements = list(expr.replace(" ", ""))
    exercise = []
    operators = ('+', '-', '*', '/', '$', '&', '@')  # @ = Average, & = Min, $ = Max
    i = 0

    while i < len(elements):
        if elements[i] == '(':
            # 寻找匹配的右括号,处理多层嵌套
            bracket_count = 1
            j = i + 1
            while j < len(elements) and bracket_count > 0:
                if elements[j] == '(':
                    bracket_count += 1
                elif elements[j] == ')':
                    bracket_count -= 1
                j += 1
            # 提取括号内的子表达式并递归计算
            sub_expr = ''.join(elements[i+1:j-1])
            sub_result = calculate_func(sub_expr)
            if sub_result is None:
                return None
            exercise.append(sub_result)
            i = j  # 跳过整个括号区域
        elif elements[i] == ')':
            print("ERROR: Mismatched parentheses.")
            return None
        elif elements[i].isdigit() or (elements[i] == '-' and (i == 0 or elements[i - 1] in operators)):
            num = elements[i]
            while i + 1 < len(elements) and (elements[i + 1].isdigit() or elements[i + 1] == '.'):
                i += 1
                num += elements[i]
            exercise.append(float(num))
        elif elements[i] in operators:
            exercise.append(elements[i])
        else:
            print(f"ERROR: Invalid character '{elements[i]}'.")
            return None
        i += 1

    return exercise

def calculate_result(expr):
    # 先解析表达式(处理括号)
    exercise = parse_expression(expr, calculate_result)
    if exercise is None:
        return None
    # 检查是否有有效数字
    if len([s for s in exercise if isinstance(s, float)]) == 0:
        print("Invalid input.")
        return None

    # 处理$ & @ 运算符(优先级最高)
    k = 0
    while k < len(exercise):
        if exercise[k] in ('$', '&', '@'):
            if k - 1 < 0 or k + 1 >= len(exercise) or not (isinstance(exercise[k-1], float) and isinstance(exercise[k+1], float)):
                print("ERROR: Invalid use of operator.")
                return None
            operator = exercise[k]
            left_num = exercise[k - 1]
            right_num = exercise[k + 1]
            if operator == '$':
                result = max(left_num, right_num)
            elif operator == '&':
                result = min(left_num, right_num)
            elif operator == '@':
                result = (left_num + right_num) / 2

            exercise[k] = result
            exercise.pop(k + 1)
            exercise.pop(k - 1)
        else:
            k += 1

    # 处理* / 运算符(优先级次之)
    k = 0
    while k < len(exercise):
        if exercise[k] in ('*', '/'):
            if k - 1 < 0 or k + 1 >= len(exercise) or not (isinstance(exercise[k-1], float) and isinstance(exercise[k+1], float)):
                print("ERROR: Invalid use of operator.")
                return None
            operator = exercise[k]
            left_num = exercise[k - 1]
            right_num = exercise[k + 1]
            if operator == '*':
                result = left_num * right_num
            elif operator == '/':
                try:
                    if right_num == 0:
                        raise ZeroDivisionError
                    result = left_num / right_num
                except ZeroDivisionError:
                    print("ERROR: Can't divide by zero.")
                    return None
            exercise[k] = result
            exercise.pop(k + 1)
            exercise.pop(k - 1)
            k -= 1  # 回退一步,避免跳过前面的运算符
        k += 1

    # 处理+ - 运算符(优先级最低)
    k = 0
    while k < len(exercise):
        if exercise[k] in ('+', '-'):
            if k - 1 < 0 or k + 1 >= len(exercise) or not (isinstance(exercise[k-1], float) and isinstance(exercise[k+1], float)):
                print("ERROR: Invalid use of operator.")
                return None
            operator = exercise[k]
            left_num = exercise[k - 1]
            right_num = exercise[k + 1]
            if operator == '+':
                result = left_num + right_num
            elif operator == '-':
                result = left_num - right_num
            exercise[k] = result
            exercise.pop(k + 1)
            exercise.pop(k - 1)
        else:
            k += 1

    if len(exercise) != 1:
        print("ERROR: Invalid expression.")
        return None
    return round(exercise[0], 2)

while True:
    expr = input("calc> ")
    if expr.lower() == 'exit':
        print("Bye")
        break
    result = calculate_result(expr)
    if result is not None:
        print(f"{expr} = {result}")

关键改动说明

  1. 递归处理括号

    • 遇到左括号时,用bracket_count统计括号数量,确保找到匹配的右括号(支持多层嵌套)。
    • 提取括号内的子表达式,递归调用calculate_result计算结果,把结果作为数字加入解析列表,跳过整个括号区域。
    • 增加括号不匹配的错误提示,比如单独出现)时直接报错。
  2. 调整函数调用逻辑

    • 让calculate_result先调用parse_expression处理括号,形成完整的递归计算流程。
    • parse_expression接收calculate_func参数,用于递归调用计算子表达式。
  3. 增强错误处理

    • 检查运算符左右是否有有效数字,避免非法表达式(比如3+$5)。
    • 最终结果列表长度必须为1,否则判定为无效表达式。
    • 简化exit输入的判断逻辑。

递归逻辑示例

比如输入((15&9)@(4*3))-2:

  1. 先计算最内层的15&9=9和4*3=12;
  2. 再计算9@12=10.5;
  3. 最后计算10.5-2=8.5。

内容的提问来源于stack exchange,提问作者fastQ

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 08:48:11