Как написать калькулятор на Python: варианты решений и советы

Раздел: Приложения на Python -> Простые учебные программы

Написание программы калькулятор на Python

Создание собственного калькулятора - один из первых практических шагов в изучении Python. Такая программа помогает освоить ввод данных, условные операторы, циклы и обработку ошибок. Далее рассмотрены основные подходы и их особенности.

Базовый консольный калькулятор с четырьмя операциями

Самый простой вариант - запросить два числа и оператор, выполнить вычисление и вывести результат. Код включает проверку деления на ноль.


# Простой калькулятор (сложение, вычитание, умножение, деление)
a = float(input("Введите первое число: "))
b = float(input("Введите второе число: "))
op = input("Введите оператор (+, -, *, /): ")

if op == "+":
    result = a + b
elif op == "-":
    result = a - b
elif op == "*":
    result = a * b
elif op == "/":
    if b == 0:
        result = "Ошибка: деление на ноль"
    else:
        result = a / b
else:
    result = "Неизвестный оператор"

print("Результат:", result)

напишите программу которая выводит привет python (написать программу выводящую 'привет' на python)

Пояснения: функция float() преобразует строку в число с плавающей точкой. Условные конструкции if/elif проверяют введенный оператор. При делении на ноль выводится сообщение об ошибке.

Типичные ошибки:

  • Ввод букв вместо чисел - вызовет ValueError. Решение: обернуть преобразование в try/except.
  • Забыть про оператор по умолчанию - программа упадет с NameError, если не определена переменная result. Рекомендуется задать начальное значение.

Как сделать калькулятор, который работает непрерывно, пока пользователь не решит выйти?


# Калькулятор с циклом while
while True:
    a = float(input("Первое число: "))
    b = float(input("Второе число: "))
    op = input("Оператор (+, -, *, /) или 'q' для выхода: ")
    if op == 'q':
        break
    if op in ('+', '-', '*', '/'):
        if op == '+':
            r = a + b
        elif op == '-':
            r = a - b
        elif op == '*':
            r = a * b
        elif op == '/':
            r = a / b if b != 0 else "Деление на ноль"
        print("Результат:", r)
    else:
        print("Неверный оператор")

написать программу калькулятор python (написать программу калькулятор на python)

Цель: многократное выполнение без перезапуска. Используется бесконечный цикл while True и условие выхода по символу 'q'. Эта конструкция удобна для учебного примера, но не защищает от повторного запроса при некорректном вводе.

Проблемы и их решения:

  • После ошибки ввода числа программа завершится - следует добавить блок try/except для повторного ввода.
  • Цикл не позволяет вернуться к предыдущему шагу - можно добавить команду 'c' для очистки или 'r' для повтора.

Как реализовать калькулятор с обработкой всех возможных ошибок ввода?


# Калькулятор с try/except
def get_number(prompt):
    while True:
        try:
            return float(input(prompt))
        except ValueError:
            print("Ошибка: введите число")

a = get_number("Введите число: ")
b = get_number("Введите число: ")
op = input("Оператор (+, -, *, /): ")
try:
    if op == '+':
        res = a + b
    elif op == '-':
        res = a - b
    elif op == '*':
        res = a * b
    elif op == '/':
        if b == 0:
            raise ZeroDivisionError("Деление на ноль")
        res = a / b
    else:
        raise ValueError("Неизвестный оператор")
    print("Результат:", res)
except ZeroDivisionError as e:
    print("Ошибка:", e)
except ValueError as e:
    print("Ошибка:", e)

В примере вынесена функция get_number, которая запрашивает число до тех пор, пока не будет получен корректный ввод. Исключения обрабатываются отдельно. Такой код более устойчив к некорректным данным.

Рекомендации:

  • Использовать пользовательские исключения для гибкой обработки.
  • Не перехватывать все исключения except: без указания типа - это скрывает ошибки программиста.

Как сделать калькулятор, принимающий выражение одной строкой (например, '2+3*4')?


# Калькулятор с eval() - осторожно!
expr = input("Введите выражение: ")
try:
    result = eval(expr)
    print("Результат:", result)
except Exception as e:
    print("Ошибка вычисления:", e)

Функция eval() выполняет строку как Python-код. Это очень удобно для простого калькулятора, но крайне опасно в реальных приложениях - злоумышленник может выполнить произвольный код (например, __import__('os').system('rm -rf /')).

Как обезопасить eval?

  • Ограничить доступные имена, передав словарь {"__builtins__": None}.
  • Использовать ast.literal_eval для безопасного вычисления литералов, но он не поддерживает операторы.
  • Лучший вариант - реализовать собственный парсер (см. examples_adv).

Как написать калькулятор с графическим интерфейсом (GUI) на Tkinter?


# Простой GUI-калькулятор (фрагмент)
import tkinter as tk

def press(key):
    entry.insert(tk.END, key)

def evaluate():
    try:
        result = eval(entry.get())
        entry.delete(0, tk.END)
        entry.insert(0, str(result))
    except:
        entry.delete(0, tk.END)
        entry.insert(0, "Ошибка")

root = tk.Tk()
root.title("Калькулятор")
entry = tk.Entry(root, width=20, font=("Arial", 16))
entry.pack()

buttons = [
    '7', '8', '9', '/',
    '4', '5', '6', '*',
    '1', '2', '3', '-',
    '0', '.', '=', '+'
]

for i, btn in enumerate(buttons):
    cmd = lambda x=btn: press(x) if x != '=' else evaluate()
    tk.Button(root, text=btn, command=cmd, width=5, height=2).grid(row=i//4+1, column=i%4)

root.mainloop()

Этот пример создает окно с полем ввода и кнопками. Кнопка '=' вычисляет выражение через eval(). Для серьезного приложения требуется заменить eval на собственную логику.

Распространенные ошибки:

  • Использование lambda без захвата значения приводит к тому, что все кнопки используют последнее значение. В коде выше применен трюк x=btn.
  • Отсутствие обработки ошибок при вычислении - при вводе некорректного выражения программа аварийно завершается.

Как добавить поддержку возведения в степень и целочисленного деления?


# Расширенный набор операций
a = float(input("Число: "))
b = float(input("Число: "))
op = input("Оператор (+, -, *, /, //, %, **): ")

operations = {
    '+': a + b,
    '-': a - b,
    '*': a * b,
    '/': a / b if b != 0 else None,
    '//': a // b if b != 0 else None,
    '%': a % b if b != 0 else None,
    '**': a ** b
}

if op in operations:
    result = operations[op]
    if result is None:
        print("Ошибка: деление на ноль")
    else:
        print("Результат:", result)
else:
    print("Неизвестная операция")

Используется словарь operations, где ключ - оператор, значение - результат. Это сокращает код и упрощает добавление новых операций.

Внимание:

  • При // и % с отрицательными числами результат может отличаться от математического ожидания - нужно помнить особенности Python.
  • Словарь вычисляется сразу при определении, что может вызвать ошибку деления на ноль еще до проверки. В примере выше использован тернарный оператор для защиты.

Расширенные примеры калькуляторов на Python

Ниже приведены более сложные и нестандартные реализации, которые демонстрируют различные возможности языка и подходы к решению задачи.

1. Калькулятор с историей операций

Программа сохраняет все вычисления в список и выводит их по запросу.

Пример

# Калькулятор с историей
history = []
while True:
    expr = input("Введите выражение (или 'h' для истории, 'q' для выхода): ")
    if expr == 'q':
        break
    if expr == 'h':
        for i, h in enumerate(history, 1):
            print(f"{i}: {h}")
        continue
    try:
        # Внимание: eval опасен, используйте с осторожностью
        result = eval(expr)
        history.append(f"{expr} = {result}")
        print("=", result)
    except Exception as e:
        print("Ошибка:", e)
Введите выражение (или 'h' для истории, 'q' для выхода): 2+3
= 5
Введите выражение (или 'h' для истории, 'q' для выхода): 10/2
= 5.0
Введите выражение (или 'h' для истории, 'q' для выхода): h
1: 2+3 = 5
2: 10/2 = 5.0
Введите выражение (или 'h' для истории, 'q' для выхода): q

Цель: демонстрация хранения данных в списке и обработки команд. Для реального использования рекомендуется вместо eval написать парсер (пример 4).

2. Калькулятор с поддержкой приоритета операций (собственный парсер)

Реализация алгоритма сортировочной станции (Shunting-yard) или рекурсивного спуска. Ниже упрощенный вариант для выражений с двумя операндами, но с приоритетом умножения и деления.

Пример

# Парсер для базовых операций с приоритетом (без скобок)
def calc(expr):
    # Разбиваем на токены (числа и операторы)
    tokens = []
    num = ''
    for ch in expr:
        if ch.isdigit() or ch == '.':
            num += ch
        else:
            if num:
                tokens.append(float(num))
                num = ''
            tokens.append(ch)
    if num:
        tokens.append(float(num))
    # Сначала умножение и деление
    i = 0
    while i < len(tokens):
        if tokens[i] in ('*', '/'):
            a = tokens[i-1]
            b = tokens[i+1]
            if tokens[i] == '*':
                tokens[i-1] = a * b
            else:
                if b == 0:
                    return "Ошибка: деление на ноль"
                tokens[i-1] = a / b
            del tokens[i:i+2]
            i -= 1
        i += 1
    # Затем сложение и вычитание
    result = tokens[0]
    for i in range(1, len(tokens), 2):
        op = tokens[i]
        b = tokens[i+1]
        if op == '+':
            result += b
        elif op == '-':
            result -= b
    return result

print(calc("2+3*4"))  # 14 (3*4=12, 2+12=14)
print(calc("10-2*3"))  # 4
14.0
4.0

Этот пример полезен для понимания принципов работы интерпретаторов. Для полноценного калькулятора потребуется поддержка скобок и унарных операторов.

3. Калькулятор с аргументами командной строки

Программа принимает выражение как аргумент при запуске и сразу выводит результат.

Пример

# calc.py - запуск: python calc.py "2+3*4"
import sys

if len(sys.argv) != 2:
    print("Использование: python calc.py 'выражение'")
    sys.exit(1)

expr = sys.argv[1]
try:
    # Безопасная замена: используем только числа и операторы
    allowed = set('0123456789.+-*/()')
    if not all(c in allowed for c in expr):
        raise ValueError("Недопустимые символы")
    result = eval(expr)  # Внимание: все равно опасно, если не фильтровать
    print(result)
except Exception as e:
    print("Ошибка:", e)
$ python calc.py "2+3"
5
$ python calc.py "10/3"
3.3333333333333335

Такой подход удобен для автоматизации и встраивания в другие скрипты. Фильтрация символов не гарантирует безопасность, но снижает риск.

4. Калькулятор с сохранением результатов в файл

Каждое вычисление записывается в текстовый файл history.txt.

Пример

# Калькулятор с логом
def log_result(expr, result):
    with open("history.txt", "a", encoding="utf-8") as f:
        f.write(f"{expr} = {result}\n")

while True:
    expr = input("Введите выражение (пусто для выхода): ")
    if not expr:
        break
    try:
        res = eval(expr)
        print("=", res)
        log_result(expr, res)
    except Exception as e:
        print("Ошибка:", e)

Просмотр истории: cat history.txt или открыть в текстовом редакторе. Цель - показать работу с файлами. Для избежания конфликтов при параллельном доступе используется режим добавления 'a'.

5. Калькулятор с поддержкой тригонометрических функций (используя math)

Расширение функциональности за счет модуля math. Ввод выражения с функциями sin, cos, sqrt и т.д.

Пример

# Калькулятор с функциями из math (безопасная eval с ограничением)
import math
import re

# Список разрешенных функций
def safe_eval(expr):
    # Проверка на недопустимые символы
    allowed = set('0123456789.+-*/() abcdefghijklmnopqrstuvwxyz_')
    if not all(c in allowed for c in expr):
        raise ValueError("Недопустимые символы")
    # Создаем безопасное окружение
    allowed_names = {k: v for k, v in math.__dict__.items() if not k.startswith("_")}
    allowed_names["__builtins__"] = None
    return eval(expr, allowed_names)

expr = input("Введите выражение (например, sin(0.5)+cos(0)): ")
try:
    result = safe_eval(expr)
    print("=", result)
except Exception as e:
    print("Ошибка:", e)
Введите выражение (например, sin(0.5)+cos(0)): sin(0.5)+cos(0)
= 1.479425538604203

Этот подход демонстрирует, как использовать eval с ограниченным пространством имен, что значительно безопаснее, чем полный доступ. Однако даже так возможно обойти ограничения через .__class__ и т.п., поэтому для серьезных проектов лучше использовать библиотеки типа numexpr или написать собственный парсер.

Написать программу калькулятор на Python - comments

En
написать программу калькулятор python (python)