loadedcheese's picture
Folders' Initial Submission
c66530c verified
raw
history blame
7.09 kB
# tools/math_tools.py
import math
from typing import Union, List, Any
from .utils import logger
Number = Union[int, float]
class MathTools:
"""Simple math tools for basic calculations and utilities"""
@staticmethod
def add(a: Number, b: Number) -> Number:
"""Return the sum of a and b"""
return a + b
@staticmethod
def subtract(a: Number, b: Number) -> Number:
"""Return the difference of a and b"""
return a - b
@staticmethod
def multiply(a: Number, b: Number) -> Number:
"""Return the product of a and b"""
return a * b
@staticmethod
def divide(a: Number, b: Number) -> Union[Number, str]:
"""Return the division of a by b, handle division by zero"""
if b == 0:
return 'Error: Division by zero'
return a / b
@staticmethod
def power(base: Number, exponent: Number) -> Number:
"""Return base raised to the power of exponent"""
return base ** exponent
@staticmethod
def factorial(n: int) -> Union[int, str]:
"""Return factorial of n (non-negative integer)"""
if not isinstance(n, int) or n < 0:
return 'Error: Input must be a non-negative integer'
if n == 0 or n == 1:
return 1
result = 1
for i in range(2, n + 1):
result *= i
return result
@staticmethod
def square_root(n: Number) -> Union[float, str]:
"""Return square root of n"""
if n < 0:
return 'Error: Cannot calculate square root of negative number'
return math.sqrt(n)
@staticmethod
def percentage(part: Number, whole: Number) -> Union[float, str]:
"""Calculate percentage: (part/whole) * 100"""
if whole == 0:
return 'Error: Cannot calculate percentage with zero denominator'
return (part / whole) * 100
@staticmethod
def average(numbers: List[Number]) -> Union[float, str]:
"""Calculate average of a list of numbers"""
if not numbers:
return 'Error: Cannot calculate average of empty list'
return sum(numbers) / len(numbers)
@staticmethod
def round_number(n: Number, decimals: int = 2) -> Number:
"""Round number to specified decimal places"""
return round(n, decimals)
@staticmethod
def absolute(n: Number) -> Number:
"""Return absolute value of n"""
return abs(n)
@staticmethod
def min_value(numbers: List[Number]) -> Union[Number, str]:
"""Find minimum value in list"""
if not numbers:
return 'Error: Cannot find minimum of empty list'
return min(numbers)
@staticmethod
def max_value(numbers: List[Number]) -> Union[Number, str]:
"""Find maximum value in list"""
if not numbers:
return 'Error: Cannot find maximum of empty list'
return max(numbers)
@staticmethod
def calculate_compound_interest(principal: Number, rate: Number, time: Number, compounds_per_year: int = 1) -> float:
"""
Calculate compound interest
Formula: A = P(1 + r/n)^(nt)
"""
return principal * (1 + rate/compounds_per_year) ** (compounds_per_year * time)
@staticmethod
def solve_quadratic(a: Number, b: Number, c: Number) -> Union[tuple, str]:
"""
Solve quadratic equation ax² + bx + c = 0
Returns tuple of solutions or error message
"""
if a == 0:
return 'Error: Not a quadratic equation (a cannot be 0)'
discriminant = b**2 - 4*a*c
if discriminant < 0:
return 'Error: No real solutions (negative discriminant)'
elif discriminant == 0:
solution = -b / (2*a)
return (solution, solution)
else:
sqrt_discriminant = math.sqrt(discriminant)
solution1 = (-b + sqrt_discriminant) / (2*a)
solution2 = (-b - sqrt_discriminant) / (2*a)
return (solution1, solution2)
# Convenience functions for direct use
def add(a: Number, b: Number) -> Number:
"""Add two numbers"""
return MathTools.add(a, b)
def subtract(a: Number, b: Number) -> Number:
"""Subtract two numbers"""
return MathTools.subtract(a, b)
def multiply(a: Number, b: Number) -> Number:
"""Multiply two numbers"""
return MathTools.multiply(a, b)
def divide(a: Number, b: Number) -> Union[Number, str]:
"""Divide two numbers"""
return MathTools.divide(a, b)
def power(base: Number, exponent: Number) -> Number:
"""Raise base to power of exponent"""
return MathTools.power(base, exponent)
def factorial(n: int) -> Union[int, str]:
"""Calculate factorial of n"""
return MathTools.factorial(n)
def square_root(n: Number) -> Union[float, str]:
"""Calculate square root"""
return MathTools.square_root(n)
def percentage(part: Number, whole: Number) -> Union[float, str]:
"""Calculate percentage"""
return MathTools.percentage(part, whole)
def average(numbers: List[Number]) -> Union[float, str]:
"""Calculate average of numbers"""
return MathTools.average(numbers)
def calculate_expression(expression: str) -> Union[Number, str]:
"""
Safely evaluate mathematical expressions
WARNING: Only use with trusted input
"""
try:
# Only allow safe mathematical operations
allowed_chars = set('0123456789+-*/().^ ')
if not all(c in allowed_chars for c in expression.replace('**', '^')):
return 'Error: Invalid characters in expression'
# Replace ^ with ** for Python exponentiation
safe_expression = expression.replace('^', '**')
# Evaluate the expression
result = eval(safe_expression)
return result
except ZeroDivisionError:
return 'Error: Division by zero in expression'
except Exception as e:
return f'Error: Invalid expression - {str(e)}'
# Example usage and testing
if __name__ == "__main__":
# Test basic operations
print("Basic Operations:")
print(f"5 + 3 = {add(5, 3)}")
print(f"10 - 4 = {subtract(10, 4)}")
print(f"6 * 7 = {multiply(6, 7)}")
print(f"15 / 3 = {divide(15, 3)}")
print(f"2^8 = {power(2, 8)}")
print("\nAdvanced Operations:")
print(f"√16 = {square_root(16)}")
print(f"5! = {factorial(5)}")
print(f"Average of [1,2,3,4,5] = {average([1,2,3,4,5])}")
percent_result = percentage(25, 100)
if isinstance(percent_result, float):
print(f"25% of 200 = {percent_result * 200 / 100}")
else:
print(f"25% of 200 = {percent_result}")
print("\nQuadratic Equation (x² - 5x + 6 = 0):")
solutions = MathTools.solve_quadratic(1, -5, 6)
print(f"Solutions: {solutions}")