import math
def add(a, b): return a + b def subtract(a, b): return a - b def multiply(a, b): return a * b
def divide(a, b): if b == 0: raise ValueError("Cannot divide by zero.") return a / b
def floor_divide(a, b): if b == 0: raise ValueError("Cannot divide by zero.") return a // b
def modulo(a, b): if b == 0: raise ValueError("Cannot mod by zero.") return a % b
def power(a, b): return a ** b
def log_base(a, b): if a <= 0: raise ValueError("Logarithm argument must be positive.") if b <= 0 or b == 1: raise ValueError("Logarithm base must be > 0 and not 1.") return math.log(a, b)
def square_root(a): if a < 0: raise ValueError("Cannot take square root of a negative number.") return math.sqrt(a)
def cube_root(a): return math.copysign(abs(a) ** (1 / 3), a)
def absolute(a): return abs(a)
def factorial(a): if a < 0 or a != int(a): raise ValueError("Factorial is only defined for non-negative integers.") return math.factorial(int(a))
def sine(a): return math.sin(math.radians(a)) def cosine(a): return math.cos(math.radians(a))
def tangent(a): if math.cos(math.radians(a)) == 0: raise ValueError("tan is undefined at this angle.") return math.tan(math.radians(a))
def natural_log(a): if a <= 0: raise ValueError("Logarithm argument must be positive.") return math.log(a)
def log10(a): if a <= 0: raise ValueError("Logarithm argument must be positive.") return math.log10(a)
def get_number(prompt): while True: try: return float(input(prompt)) except ValueError: print(" Invalid input. Please enter a number.")
TWO_OP = { "1": ("+", "Addition", add), "2": ("-", "Subtraction", subtract), "3": ("*", "Multiplication", multiply), "4": ("/", "Division", divide), "5": ("//", "Floor Division", floor_divide), "6": ("%", "Modulo", modulo), "7": ("^", "Power", power), "8": ("log_b", "Logarithm (base b)", log_base), }
ONE_OP = { "9": ("√", "Square Root", square_root), "10": ("∛", "Cube Root", cube_root), "11": ("|x|", "Absolute Value", absolute), "12": ("n!", "Factorial", factorial), "13": ("sin", "Sine (degrees)", sine), "14": ("cos", "Cosine (degrees)", cosine), "15": ("tan", "Tangent (degrees)", tangent), "16": ("ln", "Natural Log", natural_log), "17": ("log10", "Log base 10", log10), }
QUIT_KEY = "0"
def calculator(): print("\n" + "=" * 40) print(" Python Calculator") print("=" * 40)
while True:
print("\n── Two-operand operations ──")
for key, (symbol, label, _) in TWO_OP.items():
print(f" {key:>2}. {symbol:<8} {label}")
print("\n── Single-operand operations ──")
for key, (symbol, label, _) in ONE_OP.items():
print(f" {key:>2}. {symbol:<8} {label}")
print(f"\n {QUIT_KEY}. Quit")
all_keys = list(TWO_OP) + list(ONE_OP) + [QUIT_KEY]
choice = input("\nSelect an operation: ").strip()
if choice == QUIT_KEY:
print("Goodbye!")
break
if choice not in all_keys:
print(" Invalid choice.")
continue
try:
if choice in TWO_OP:
symbol, label, func = TWO_OP[choice]
a = get_number("Enter first number: ")
b = get_number("Enter second number: ")
result = func(a, b)
print(f"\n {a} {symbol} {b} = {result}")
else:
symbol, label, func = ONE_OP[choice]
a = get_number("Enter number: ")
result = func(a)
print(f"\n {symbol}({a}) = {result}")
except ValueError as e:
print(f" Error: {e}")
if name == "main": calculator()