openuiX / calculator.py
iridescentX's picture
Upload calculator.py
7432bb1 verified
raw
history blame
6.79 kB
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."