Spaces:
Paused
Paused
| import ast | |
| import operator | |
| import math | |
| import sympy as sp | |
| import re | |
| class Tools: | |
| def __init__(self): | |
| self.citation = True | |
| def calculator(self, equations: str) -> str: | |
| """ | |
| Calculate the result of a simple equation or comparison. | |
| :param equation: The equation to calculate or compare. | |
| - For arithmetic operations: Use operators like +, -, *, /, **, //, % | |
| - For comparisons: Use operators like >, <, >=, <=, ==, != | |
| - For solving systems of equations, separate equations with a semicolon (e.g., 'x + y = 30; 2*x + 4*y = 80') | |
| - Evaluating multiple expressions separated by commas (e.g., '-1/27, 19/52') | |
| - Example inputs: "3 + 5", "10 / 2", "e ** 2", "pi > 3", "3.11 < 3.8" | |
| """ | |
| # 预处理:自动添加乘号 | |
| modified_equations = re.sub(r"(\d)([a-zA-Z])", r"\1*\2", equations) | |
| modified_equations = modified_equations.replace("^", "**") | |
| # 检测和解决方程组 | |
| if "=" in modified_equations: | |
| try: | |
| # 分割多个方程(如果有的话) | |
| eq_list = modified_equations.split(";") | |
| if len(eq_list) > 1: | |
| # 检测到多个方程,作为方程组求解 | |
| equations_sym = [] | |
| symbols = set() | |
| for eq in eq_list: | |
| left_expr, right_expr = eq.split("=") | |
| left_sym = sp.sympify(left_expr) | |
| right_sym = sp.sympify(right_expr) | |
| symbols |= left_sym.free_symbols | right_sym.free_symbols | |
| equations_sym.append(left_sym - right_sym) | |
| solution = sp.solve(equations_sym, list(symbols)) | |
| # 格式化输出结果为“变量 = 解”的形式 | |
| solution_str = ", ".join( | |
| f"{str(var)} = {sol}" for var, sol in solution.items() | |
| ) | |
| return f"The solution to the system of equations '{equations}' is {solution_str}. Provide this solution to the user." | |
| else: | |
| # 单个方程,正常求解 | |
| left_expr, right_expr = eq_list[0].split("=") | |
| left_sym = sp.sympify(left_expr) | |
| right_sym = sp.sympify(right_expr) | |
| symbols = list(left_sym.free_symbols | right_sym.free_symbols) | |
| if len(symbols) != 1: | |
| return f"The equation '{equations}' contains {len(symbols)} variables. Please provide an equation with only one variable." | |
| solution = sp.solve(left_sym - right_sym, symbols[0]) | |
| return f"The solution to the equation '{equations}' is {symbols[0]} = {solution[0]}. Provide this solution to the user." | |
| except Exception as e: | |
| return f"There was an error solving the equation(s) '{equations}': {str(e)}. Notify the user about the issue." | |
| ops = { | |
| ast.Add: operator.add, | |
| ast.Sub: operator.sub, | |
| ast.Mult: operator.mul, | |
| ast.Div: operator.truediv, | |
| ast.Pow: operator.pow, | |
| ast.Mod: operator.mod, | |
| ast.FloorDiv: operator.floordiv, | |
| ast.BitXor: operator.xor, | |
| ast.BitAnd: operator.and_, | |
| ast.BitOr: operator.or_, | |
| } | |
| unary_ops = { | |
| ast.UAdd: operator.pos, | |
| ast.USub: operator.neg, | |
| } | |
| compare_ops = { | |
| ast.Gt: operator.gt, | |
| ast.Lt: operator.lt, | |
| ast.GtE: operator.ge, | |
| ast.LtE: operator.le, | |
| ast.Eq: operator.eq, | |
| ast.NotEq: operator.ne, | |
| } | |
| def eval_expr(node): | |
| if isinstance(node, ast.Num): | |
| return node.n | |
| elif isinstance(node, ast.Constant): | |
| return node.value | |
| elif isinstance(node, ast.Tuple): # 处理元组输入 | |
| return tuple(eval_expr(elt) for elt in node.elts) | |
| elif isinstance(node, ast.Name): | |
| if node.id == "pi": | |
| return math.pi | |
| elif node.id == "e": | |
| return math.e | |
| else: | |
| raise ValueError(f"Unsupported constant: {node.id}") | |
| elif isinstance(node, ast.BinOp): | |
| if type(node.op) in ops: | |
| return ops[type(node.op)]( | |
| eval_expr(node.left), eval_expr(node.right) | |
| ) | |
| else: | |
| raise ValueError(f"Unsupported operation: {type(node.op).__name__}") | |
| elif isinstance(node, ast.UnaryOp): | |
| if type(node.op) in unary_ops: | |
| return unary_ops[type(node.op)](eval_expr(node.operand)) | |
| else: | |
| raise ValueError( | |
| f"Unsupported unary operation: {type(node.op).__name__}" | |
| ) | |
| elif isinstance(node, ast.Compare): | |
| if len(node.ops) == 1: | |
| op = node.ops[0] | |
| if type(op) in compare_ops: | |
| return compare_ops[type(op)]( | |
| eval_expr(node.left), eval_expr(node.comparators[0]) | |
| ) | |
| else: | |
| raise ValueError(f"Unsupported comparison: {type(op).__name__}") | |
| else: | |
| raise ValueError("Unsupported multiple comparisons") | |
| else: | |
| raise ValueError(f"Unsupported expression type: {type(node).__name__}") | |
| try: | |
| parsed = ast.parse(modified_equations, mode="eval") | |
| result = eval_expr(parsed.body) | |
| if isinstance(result, bool): | |
| return f"The comparison '{equations}' evaluates to {result}. Respond accordingly." | |
| else: | |
| return f"The result of the expression '{equations}' is {result}. Provide this information to the user." | |
| except (SyntaxError, ValueError) as e: | |
| return f"There is an error in the expression '{equations}': {str(e)}. Notify the user about the issue." | |
| except ZeroDivisionError: | |
| return f"The expression '{equations}' involves a division by zero, which is undefined. Inform the user about this error." | |
| except Exception as e: | |
| return f"The expression '{equations}' is invalid: {str(e)}. Let the user know that there was a mistake." | |