Calculator Program in Python
Beginner · Useful tools · about 40 minutes to build · 125 lines
Pick an operation from a menu, type two numbers and get the answer, with every result kept in a history you can look back at.
The program
Press Run and answer its questions in the box that appears under the code.
Open it in the full editor to save it, share it and keep building.
Sample run
What the program printed, and what was typed (in yellow).
Calculator
1) Add 2) Subtract 3) Multiply 4) Divide
5) Power 6) Remainder 7) History 8) Quit
Choose 1-8: 1
First number: 12
Second number: 30
Add: 12 + 30 = 42
1) Add 2) Subtract 3) Multiply 4) Divide
5) Power 6) Remainder 7) History 8) Quit
Choose 1-8: 4
First number: 7
Second number: 0
You cannot divide by zero.
1) Add 2) Subtract 3) Multiply 4) Divide
5) Power 6) Remainder 7) History 8) Quit
Choose 1-8: 3
First number: abc
That is not a number. Try something like 12 or 3.5.
First number: 2.5
Second number: 4
Multiply: 2.5 * 4 = 10
1) Add 2) Subtract 3) Multiply 4) Divide
5) Power 6) Remainder 7) History 8) Quit
Choose 1-8: 5
First number: 2
Second number: 10
Power: 2 ^ 10 = 1024
1) Add 2) Subtract 3) Multiply 4) Divide
5) Power 6) Remainder 7) History 8) Quit
Choose 1-8: 0
Please choose a number from the menu.
1) Add 2) Subtract 3) Multiply 4) Divide
5) Power 6) Remainder 7) History 8) Quit
Choose 1-8: 7
History:
1. 12 + 30 = 42
2. 2.5 * 4 = 10
3. 2 ^ 10 = 1024
1) Add 2) Subtract 3) Multiply 4) Divide
5) Power 6) Remainder 7) History 8) Quit
Choose 1-8: 8
Goodbye. You made 3 calculation(s).How it is built
1. The operations in one dictionary
Each menu number maps to a name and a symbol. The menu, the sums and the history all read from OPERATIONS, so a new operation starts with one new line here.
# Menu number -> (name shown in the menu, symbol shown in the history) OPERATIONS = { "1": ("Add", "+"), "2": ("Subtract", "-"), "3": ("Multiply", "*"), "4": ("Divide", "/"), "5": ("Power", "^"), "6": ("Remainder", "%"), } HISTORY_CHOICE = "7" QUIT_CHOICE = "8" MENU_COLUMNS = 4
2. Reading a number safely
float() raises ValueError for text like abc, so the loop catches it and asks again. math.isfinite also turns away inf and nan, which float() would accept.
def read_number(prompt): """Ask until the user types an ordinary number.""" while True: text = input(prompt).strip() try: value = float(text) except ValueError: print(" That is not a number. Try something like 12 or 3.5.") continue if math.isfinite(value): return value print(" Please type an ordinary number.")
3. Doing the sums
Each if returns its answer straight away, so no elif chain is needed. Python writes powers as **; the history shows them as ^.
def calculate(a, b, symbol): """Return the result of a <symbol> b.""" if symbol == "+": return a + b if symbol == "-": return a - b if symbol == "*": return a * b if symbol == "/": return a / b if symbol == "%": return a % b return a ** b
4. Catching the impossible
Dividing by zero raises ZeroDivisionError and a huge power raises OverflowError, so both become friendly messages. A finished sum is stored as a line of text in the history list.
def run_operation(choice, history): """Ask for two numbers, print the answer and add it to the history.""" name, symbol = OPERATIONS[choice] a = read_number("First number: ") b = read_number("Second number: ") try: result = calculate(a, b, symbol) except ZeroDivisionError: print(" You cannot divide by zero.") return except OverflowError: print(" That answer is too large to show.") return # A negative number to a fractional power gives a complex number if isinstance(result, complex): print(" That power has no real-number answer.") return if not math.isfinite(result): print(" That answer is too large to show.") return line = f"{format_number(a)} {symbol} {format_number(b)} = {format_number(result)}" history.append(line) print(f" {name}: {line}")
5. The main loop
history is created inside main() and handed to the functions that need it. The loop keeps showing the menu until the user picks Quit, and break ends it.
def main(): """Show the menu and run the user's choices until they quit.""" history = [] print("Calculator") while True: print() show_menu() choice = input(f"Choose 1-{QUIT_CHOICE}: ").strip() if choice in OPERATIONS: run_operation(choice, history) elif choice == HISTORY_CHOICE: show_history(history) elif choice == QUIT_CHOICE: print(f"Goodbye. You made {len(history)} calculation(s).") break else: print(" Please choose a number from the menu.")
Make it bigger
- Let the user type
ansinstead of a number to reuse the last answer. - Add square root and percentage as new entries in
OPERATIONS. - Save the history to a text file when the user quits and load it the next time.
- Accept a whole sum on one line, such as
12 * 4, and split it into its parts.