diff --git a/README.md b/README.md new file mode 100644 index 0000000..9afa0e2 --- /dev/null +++ b/README.md @@ -0,0 +1,107 @@ +# Python Calculator Applications + +This repository contains two different calculator implementations in Python: + +## 1. GUI Calculator (`calculator.py`) + +A modern graphical calculator with a beautiful interface built using tkinter. + +### Features: +- Modern dark theme UI +- Standard calculator operations (+, -, ร—, รท) +- Special functions (%, ยฑ, Clear) +- Keyboard support +- Error handling for division by zero +- Large, easy-to-read display + +### How to run: +```bash +python3 calculator.py +``` + +### Keyboard shortcuts: +- Number keys (0-9): Input numbers +- `.`: Decimal point +- `+`, `-`, `*`, `/`: Basic operations +- `=` or `Enter`: Calculate result +- `Backspace`: Clear +- `%`: Percentage + +## 2. Command Line Calculator (`simple_calculator.py`) + +A feature-rich command-line calculator that supports both interactive mode and direct calculations. + +### Features: +- Interactive mode with history +- Support for complex mathematical expressions +- Built-in math functions (sin, cos, tan, sqrt, log) +- Mathematical constants (pi, e) +- Percentage calculations +- Command-line argument support +- Calculation history + +### How to run: + +#### Interactive mode: +```bash +python3 simple_calculator.py +``` + +#### Direct calculation: +```bash +python3 simple_calculator.py 10 + 5 +python3 simple_calculator.py "sqrt(16)" +python3 simple_calculator.py "2 * pi * 5" +``` + +### Supported operations: +- Basic arithmetic: `+`, `-`, `*`, `/`, `**` (power), `%` (modulo) +- Functions: `sqrt(x)`, `sin(x)`, `cos(x)`, `tan(x)`, `log(x)`, `log10(x)` +- Constants: `pi`, `e` +- Special: `15% of 200` (percentage calculations) + +### Interactive commands: +- `history`: Show calculation history +- `clear`: Clear history +- `quit` or `exit`: Exit calculator + +## Requirements + +Both calculators use only Python standard library modules: +- `tkinter` (for GUI calculator) +- `math` (for mathematical functions) +- `sys` (for command-line arguments) + +No additional packages need to be installed. + +## Examples + +### GUI Calculator: +Just run the program and click buttons or use keyboard shortcuts. + +### Command Line Calculator: +```bash +# Interactive mode examples: +๐Ÿ“ฑ Calculate: 2 + 3 * 4 +๐Ÿ“Š Result: 14 + +๐Ÿ“ฑ Calculate: sqrt(25) +๐Ÿ“Š Result: 5 + +๐Ÿ“ฑ Calculate: sin(pi/2) +๐Ÿ“Š Result: 1 + +๐Ÿ“ฑ Calculate: 15% of 200 +๐Ÿ“Š Result: 30 + +# Command line examples: +python3 simple_calculator.py 25 + 17 +# Result: 42 + +python3 simple_calculator.py "sqrt(144)" +# Result: 12 +``` + +## License + +This project is open source and available under the MIT License. \ No newline at end of file diff --git a/calculator.py b/calculator.py new file mode 100644 index 0000000..78b7de8 --- /dev/null +++ b/calculator.py @@ -0,0 +1,266 @@ +import tkinter as tk +from tkinter import ttk +import math + +class Calculator: + def __init__(self, root): + self.root = root + self.root.title("Calculator") + self.root.geometry("350x500") + self.root.resizable(False, False) + self.root.configure(bg='#2c3e50') + + # Variables + self.current = "0" + self.previous = "" + self.operator = "" + self.should_reset = False + + self.create_widgets() + + def create_widgets(self): + # Display frame + display_frame = tk.Frame(self.root, bg='#2c3e50', pady=20) + display_frame.pack(fill='x', padx=20) + + # Display + self.display = tk.Label( + display_frame, + text="0", + font=("Arial", 24, "bold"), + bg='#34495e', + fg='white', + anchor='e', + padx=20, + pady=20, + relief='sunken', + bd=2 + ) + self.display.pack(fill='x') + + # Button frame + button_frame = tk.Frame(self.root, bg='#2c3e50') + button_frame.pack(fill='both', expand=True, padx=20, pady=(0, 20)) + + # Button style configuration + self.create_buttons(button_frame) + + def create_buttons(self, parent): + # Button layout + buttons = [ + ['C', 'ยฑ', '%', 'รท'], + ['7', '8', '9', 'ร—'], + ['4', '5', '6', 'โˆ’'], + ['1', '2', '3', '+'], + ['0', '.', '=', '='] + ] + + # Colors + number_color = '#95a5a6' + operator_color = '#e74c3c' + special_color = '#3498db' + + for i, row in enumerate(buttons): + for j, text in enumerate(row): + if text == '=': + if j == 2: # First equals button + continue + # Make equals button span 2 columns + btn = tk.Button( + parent, + text=text, + font=("Arial", 18, "bold"), + bg=operator_color, + fg='white', + bd=0, + pady=15, + command=lambda t=text: self.button_click(t) + ) + btn.grid(row=i, column=j-1, columnspan=2, sticky='nsew', padx=2, pady=2) + else: + # Determine button color + if text in ['C', 'ยฑ', '%']: + bg_color = special_color + elif text in ['รท', 'ร—', 'โˆ’', '+']: + bg_color = operator_color + else: + bg_color = number_color + + # Special case for 0 button + if text == '0': + btn = tk.Button( + parent, + text=text, + font=("Arial", 18, "bold"), + bg=bg_color, + fg='white', + bd=0, + pady=15, + command=lambda t=text: self.button_click(t) + ) + btn.grid(row=i, column=j, columnspan=2, sticky='nsew', padx=2, pady=2) + else: + btn = tk.Button( + parent, + text=text, + font=("Arial", 18, "bold"), + bg=bg_color, + fg='white', + bd=0, + pady=15, + command=lambda t=text: self.button_click(t) + ) + btn.grid(row=i, column=j, sticky='nsew', padx=2, pady=2) + + # Configure grid weights + for i in range(5): + parent.grid_rowconfigure(i, weight=1) + for j in range(4): + parent.grid_columnconfigure(j, weight=1) + + def button_click(self, char): + if char.isdigit() or char == '.': + self.input_number(char) + elif char in ['รท', 'ร—', 'โˆ’', '+']: + self.input_operator(char) + elif char == '=': + self.calculate() + elif char == 'C': + self.clear() + elif char == 'ยฑ': + self.toggle_sign() + elif char == '%': + self.percentage() + + def input_number(self, char): + if self.should_reset: + self.current = "0" + self.should_reset = False + + if char == '.': + if '.' not in self.current: + self.current += char + else: + if self.current == "0": + self.current = char + else: + self.current += char + + self.update_display() + + def input_operator(self, op): + if self.operator and not self.should_reset: + self.calculate() + + self.previous = self.current + self.operator = op + self.should_reset = True + + def calculate(self): + if not self.operator or not self.previous: + return + + try: + prev = float(self.previous) + curr = float(self.current) + + if self.operator == '+': + result = prev + curr + elif self.operator == 'โˆ’': + result = prev - curr + elif self.operator == 'ร—': + result = prev * curr + elif self.operator == 'รท': + if curr == 0: + self.current = "Error" + self.update_display() + self.clear() + return + result = prev / curr + + # Format result + if result == int(result): + self.current = str(int(result)) + else: + self.current = f"{result:.10g}" + + self.operator = "" + self.previous = "" + self.should_reset = True + + except (ValueError, ZeroDivisionError): + self.current = "Error" + self.clear() + + self.update_display() + + def clear(self): + self.current = "0" + self.previous = "" + self.operator = "" + self.should_reset = False + self.update_display() + + def toggle_sign(self): + if self.current != "0" and self.current != "Error": + if self.current.startswith('-'): + self.current = self.current[1:] + else: + self.current = '-' + self.current + self.update_display() + + def percentage(self): + try: + value = float(self.current) / 100 + if value == int(value): + self.current = str(int(value)) + else: + self.current = f"{value:.10g}" + self.update_display() + self.should_reset = True + except ValueError: + pass + + def update_display(self): + # Limit display length + display_text = self.current + if len(display_text) > 15: + try: + value = float(display_text) + display_text = f"{value:.6e}" + except ValueError: + display_text = display_text[:15] + + self.display.config(text=display_text) + +def main(): + root = tk.Tk() + calculator = Calculator(root) + + # Keyboard bindings + def key_press(event): + key = event.char + if key.isdigit() or key == '.': + calculator.button_click(key) + elif key == '+': + calculator.button_click('+') + elif key == '-': + calculator.button_click('โˆ’') + elif key == '*': + calculator.button_click('ร—') + elif key == '/': + calculator.button_click('รท') + elif key == '\r' or key == '=': # Enter key + calculator.button_click('=') + elif key == '\x08': # Backspace + calculator.button_click('C') + elif key == '%': + calculator.button_click('%') + + root.bind('', key_press) + root.focus_set() + + root.mainloop() + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/simple_calculator.py b/simple_calculator.py new file mode 100644 index 0000000..3453b28 --- /dev/null +++ b/simple_calculator.py @@ -0,0 +1,179 @@ +#!/usr/bin/env python3 +""" +Simple Command Line Calculator +Supports basic arithmetic operations and some advanced functions. +""" + +import math +import sys + +class SimpleCalculator: + def __init__(self): + self.history = [] + self.last_result = 0 + + def add(self, a, b): + """Addition""" + return a + b + + def subtract(self, a, b): + """Subtraction""" + return a - b + + def multiply(self, a, b): + """Multiplication""" + return a * b + + def divide(self, a, b): + """Division""" + if b == 0: + raise ValueError("Cannot divide by zero!") + return a / b + + def power(self, a, b): + """Exponentiation""" + return a ** b + + def square_root(self, a): + """Square root""" + if a < 0: + raise ValueError("Cannot calculate square root of negative number!") + return math.sqrt(a) + + def percentage(self, a, b): + """Calculate percentage: a% of b""" + return (a / 100) * b + + def evaluate_expression(self, expression): + """Safely evaluate mathematical expressions""" + try: + # Replace common symbols + expression = expression.replace('x', '*').replace('X', '*') + expression = expression.replace('^', '**') + + # Add support for common math functions + safe_dict = { + "__builtins__": {}, + "abs": abs, + "round": round, + "pow": pow, + "sqrt": math.sqrt, + "sin": math.sin, + "cos": math.cos, + "tan": math.tan, + "log": math.log, + "log10": math.log10, + "pi": math.pi, + "e": math.e, + } + + result = eval(expression, safe_dict) + return result + except Exception as e: + raise ValueError(f"Invalid expression: {e}") + + def run_interactive(self): + """Run calculator in interactive mode""" + print("๐Ÿงฎ Python Calculator") + print("=" * 40) + print("Enter mathematical expressions or use these commands:") + print(" Basic: +, -, *, /, ** (power), % (modulo)") + print(" Functions: sqrt(x), sin(x), cos(x), tan(x), log(x)") + print(" Constants: pi, e") + print(" Commands: 'quit' or 'exit' to stop, 'history' to see past calculations") + print(" Examples: 2 + 3, sqrt(16), sin(pi/2), 15% of 200") + print("=" * 40) + + while True: + try: + user_input = input("\n๐Ÿ“ฑ Calculate: ").strip() + + if user_input.lower() in ['quit', 'exit', 'q']: + print("๐Ÿ‘‹ Goodbye!") + break + + if user_input.lower() == 'history': + self.show_history() + continue + + if user_input.lower() == 'clear': + self.history.clear() + print("๐Ÿ—‘๏ธ History cleared!") + continue + + if not user_input: + continue + + # Handle percentage calculations + if 'of' in user_input.lower() and '%' in user_input: + parts = user_input.lower().split('of') + if len(parts) == 2: + percentage = float(parts[0].strip().replace('%', '')) + value = float(parts[1].strip()) + result = self.percentage(percentage, value) + else: + result = self.evaluate_expression(user_input) + else: + result = self.evaluate_expression(user_input) + + # Format result + if isinstance(result, float) and result.is_integer(): + result = int(result) + + self.last_result = result + self.history.append(f"{user_input} = {result}") + + print(f"๐Ÿ“Š Result: {result}") + + except KeyboardInterrupt: + print("\n๐Ÿ‘‹ Goodbye!") + break + except ValueError as e: + print(f"โŒ Error: {e}") + except Exception as e: + print(f"โŒ Unexpected error: {e}") + + def show_history(self): + """Display calculation history""" + if not self.history: + print("๐Ÿ“ No calculations in history.") + return + + print("\n๐Ÿ“œ Calculation History:") + print("-" * 30) + for i, calculation in enumerate(self.history[-10:], 1): # Show last 10 + print(f"{i:2d}. {calculation}") + + def calculate_from_args(self, args): + """Calculate from command line arguments""" + if len(args) < 1: + print("Usage: python simple_calculator.py ") + print("Examples:") + print(" python simple_calculator.py 10 + 5") + print(" python simple_calculator.py \"sqrt(16)\"") + print(" python simple_calculator.py \"2 * pi\"") + return + + try: + expression = " ".join(args) + result = self.evaluate_expression(expression) + + if isinstance(result, float) and result.is_integer(): + result = int(result) + + print(f"Result: {result}") + + except Exception as e: + print(f"Error: {e}") + +def main(): + calculator = SimpleCalculator() + + # Check if command line arguments are provided + if len(sys.argv) > 1: + calculator.calculate_from_args(sys.argv[1:]) + else: + calculator.run_interactive() + +if __name__ == "__main__": + main() \ No newline at end of file