📜  门| GATE IT 2006 |问题28(1)

📅  最后修改于: 2023-12-03 15:42:14.131000             🧑  作者: Mango

问题28 - GATE IT 2006

题目描述

给定一个将数值与函数符号组合而成的字符串,设计程序对其进行求值。

输入格式

一个长度不超过100的字符串,其中包含任意个数的整数和以下函数符号:

  1. +:表示加法
  2. -:表示减法
  3. *:表示乘法
  4. /:表示除法
  5. ^:表示指数运算
  6. %:表示取模运算
  7. sqrt:表示开方运算
  8. sin:表示正弦函数
  9. cos:表示余弦函数
  10. tan:表示正切函数
输出格式

一个整数,为字符串表达式的求值结果。如果表达式非法,则输出 ERROR

示例输入
25+3*4-1+sqrt(4)
示例输出
42
说明

该字符串表达式等价于 ((25 + (3 * 4)) - 1) + sqrt(4)

解题思路

这是一道计算器表达式求值的题目,可以通过将表达式转换成后缀表达式来求值。

具体做法是,使用栈来保存操作数和操作符:

  1. 遇到数字,入栈。
  2. 遇到操作符,判断优先级,将栈中所有优先级高于等于该操作符的操作符弹出,计算出栈顶的两个操作数并将结果入栈。
  3. 将该操作符入栈。
  4. 如果遇到左括号,直接入栈。
  5. 如果遇到右括号,将栈中所有左括号到右括号之间的操作符弹出,计算出栈顶的两个操作数并将结果入栈。

最后,栈中剩下的数即为表达式的值。

代码实现
def evaluate_expression(expression: str) -> Union[int, str]:
    """
    计算数值表达式的值
    :param expression: 字符串数值表达式
    :return: 求值结果或错误信息
    """
    operators = {
        '+': 1,
        '-': 1,
        '*': 2,
        '/': 2,
        '%': 2,
        '^': 3,
        'sqrt': 4,
        'sin': 4,
        'cos': 4,
        'tan': 4
    }
    operator_stack = []
    operand_stack = []
    i = 0
    while i < len(expression):
        if expression[i].isdigit():
            j = i
            while j < len(expression) and expression[j].isdigit():
                j += 1
            num = int(expression[i:j])
            operand_stack.append(num)
            i = j
        elif expression[i] in operators:
            while operator_stack and operator_stack[-1] != '(' and operators[expression[i]] <= operators[operator_stack[-1]]:
                operator = operator_stack.pop()
                if operator in ['+', '-', '*', '/', '%', '^']:
                    b = operand_stack.pop()
                    a = operand_stack.pop()
                    if operator == '+':
                        operand_stack.append(a + b)
                    elif operator == '-':
                        operand_stack.append(a - b)
                    elif operator == '*':
                        operand_stack.append(a * b)
                    elif operator == '/':
                        operand_stack.append(a // b)
                    elif operator == '%':
                        operand_stack.append(a % b)
                    elif operator == '^':
                        operand_stack.append(a ** b)
                elif operator == 'sqrt':
                    operand_stack.append(int(operand_stack.pop() ** 0.5))
                elif operator == 'sin':
                    operand_stack.append(int(math.sin(math.radians(operand_stack.pop()))))
                elif operator == 'cos':
                    operand_stack.append(int(math.cos(math.radians(operand_stack.pop()))))
                elif operator == 'tan':
                    operand_stack.append(int(math.tan(math.radians(operand_stack.pop()))))
            operator_stack.append(expression[i])
            i += 1
        elif expression[i] == '(':
            operator_stack.append(expression[i])
            i += 1
        elif expression[i] == ')':
            while operator_stack[-1] != '(':
                operator = operator_stack.pop()
                if operator in ['+', '-', '*', '/', '%', '^']:
                    b = operand_stack.pop()
                    a = operand_stack.pop()
                    if operator == '+':
                        operand_stack.append(a + b)
                    elif operator == '-':
                        operand_stack.append(a - b)
                    elif operator == '*':
                        operand_stack.append(a * b)
                    elif operator == '/':
                        operand_stack.append(a // b)
                    elif operator == '%':
                        operand_stack.append(a % b)
                    elif operator == '^':
                        operand_stack.append(a ** b)
                elif operator == 'sqrt':
                    operand_stack.append(int(operand_stack.pop() ** 0.5))
                elif operator == 'sin':
                    operand_stack.append(int(math.sin(math.radians(operand_stack.pop()))))
                elif operator == 'cos':
                    operand_stack.append(int(math.cos(math.radians(operand_stack.pop()))))
                elif operator == 'tan':
                    operand_stack.append(int(math.tan(math.radians(operand_stack.pop()))))
            operator_stack.pop()
            i += 1

    while operator_stack:
        operator = operator_stack.pop()
        if operator in ['+', '-', '*', '/', '%', '^']:
            b = operand_stack.pop()
            a = operand_stack.pop()
            if operator == '+':
                operand_stack.append(a + b)
            elif operator == '-':
                operand_stack.append(a - b)
            elif operator == '*':
                operand_stack.append(a * b)
            elif operator == '/':
                operand_stack.append(a // b)
            elif operator == '%':
                operand_stack.append(a % b)
            elif operator == '^':
                operand_stack.append(a ** b)
        elif operator == 'sqrt':
            operand_stack.append(int(operand_stack.pop() ** 0.5))
        elif operator == 'sin':
            operand_stack.append(int(math.sin(math.radians(operand_stack.pop()))))
        elif operator == 'cos':
            operand_stack.append(int(math.cos(math.radians(operand_stack.pop()))))
        elif operator == 'tan':
            operand_stack.append(int(math.tan(math.radians(operand_stack.pop()))))

    if len(operand_stack) == 1:
        return operand_stack[0]
    else:
        return 'ERROR'
复杂度分析

该算法的时间复杂度为 $O(n)$,其中 $n$ 为输入字符串的长度。算法使用了两个栈,空间复杂度为 $O(n)$。