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

如何实现禁用eval的单变量字符串表达式计算函数

问题描述

需求:实现一个单变量函数calculate_from_string,输入为包含+-*/数学运算的字符串表达式(如"5+3"),调用后需返回对应计算结果(如8)。本人尝试多种方法均未成功,且代码中禁止使用eval函数。相关代码定义如下:

def calculate_from_string(string):
    # 我试了很多方法都没成功,而且这段代码里不能用eval函数。
解决方案

基础版:处理二元运算

适用于仅包含两个操作数和一个运算符的简单表达式(如"5+3"、"12/4"):

def calculate_from_string(string):
    # 映射运算符到对应的计算逻辑
    op_handlers = {
        '+': lambda a, b: a + b,
        '-': lambda a, b: a - b,
        '*': lambda a, b: a * b,
        '/': lambda a, b: a / b  # 若需整数除法,替换为//
    }

    # 遍历运算符拆分表达式
    for op in op_handlers:
        if op in string:
            num1_str, num2_str = string.split(op)
            try:
                # 转换为数值并去除可能的空格
                num1 = float(num1_str.strip())
                num2 = float(num2_str.strip())
                return op_handlers[op](num1, num2)
            except ValueError:
                raise ValueError("输入表达式格式错误,请确保是合法的数字运算")
    
    # 处理单独数字的情况
    try:
        return float(string.strip())
    except ValueError:
        raise ValueError("输入表达式格式错误")

进阶版:支持多运算符与运算优先级

如果需要处理"3+4*2"、"10/2-3"这类包含运算优先级的复杂表达式,可通过**中缀转后缀表达式(逆波兰表达式)**实现:

def calculate_from_string(string):
    # 定义运算符优先级
    op_precedence = {'+': 1, '-': 1, '*': 2, '/': 2}
    output_queue = []
    op_stack = []
    tokens = []

    # 拆分表达式为数字和运算符的token列表
    i = 0
    str_len = len(string)
    while i < str_len:
        # 提取数字(支持小数)
        if string[i].isdigit() or string[i] == '.':
            j = i
            while j < str_len and (string[j].isdigit() or string[j] == '.'):
                j += 1
            tokens.append(string[i:j])
            i = j
        # 提取运算符
        elif string[i] in '+-*/':
            tokens.append(string[i])
            i += 1
        # 跳过空格
        elif string[i].isspace():
            i += 1
        else:
            raise ValueError(f"表达式包含无效字符:{string[i]}")

    # 中缀表达式转后缀表达式
    for token in tokens:
        if token.replace('.', '', 1).isdigit():
            output_queue.append(float(token))
        else:
            # 弹出优先级不低于当前运算符的栈顶元素
            while op_stack and op_precedence[op_stack[-1]] >= op_precedence[token]:
                output_queue.append(op_stack.pop())
            op_stack.append(token)
    # 弹出剩余运算符
    while op_stack:
        output_queue.append(op_stack.pop())

    # 计算后缀表达式
    calc_stack = []
    for item in output_queue:
        if isinstance(item, float):
            calc_stack.append(item)
        else:
            b = calc_stack.pop()
            a = calc_stack.pop()
            if item == '+':
                calc_stack.append(a + b)
            elif item == '-':
                calc_stack.append(a - b)
            elif item == '*':
                calc_stack.append(a * b)
            elif item == '/':
                if b == 0:
                    raise ZeroDivisionError("除数不能为0")
                calc_stack.append(a / b)
    
    if len(calc_stack) != 1:
        raise ValueError("输入表达式格式错误")
    return calc_stack[0]

使用示例

# 基础版测试
print(calculate_from_string("5+3"))  # 输出 8.0
print(calculate_from_string("12/4")) # 输出 3.0

# 进阶版测试
print(calculate_from_string("3+4*2"))  # 输出 11.0
print(calculate_from_string("10/2-3")) # 输出 2.0

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 21:27:25