# Калькулятор (Python CLI) Лёгкий интерактивный калькулятор на чистом Python — без внешних зависимостей. ## Возможности - Операции: `+ - * / //` (целочисленное), скобки `()` - Приоритет операций (скобки меняют порядок) - Унарный минус/плюс: `-5`, `+3` - Проценты: `50 %` → `0.5`; `7 % 3` → `1` (бинарный остаток; `%` без правого операнда = процент) - Возведение в степень: `2 ** 10` (правостороннее) - Экспоненциальная запись: `1e3`, `2.5E-4`; разделители разрядов: `1_000_000` - Константы: `pi`, `e`, `tau`, `inf` (регистр не важен) - Функции: `sqrt`, `abs`, `exp`, `ln`, `log`, `log2`, `log10`, `round`, `floor`, `ceil`, `sin`, `cos`, `tan`, `asin`, `acos`, `atan` (тригонометрия — в радианах) - Деление на ноль обрабатывается красиво (без падения с exception) - Переменная `ans` — последнее вычисление (можно подставить: `ans + 4`) - История вычислений и команды сессии (`help`, `vars`, `hist`, `reset`) в интерактивном режиме - Форматирование результата: без артефактов float (`0.1 + 0.2` → `0.3`) - Сообщения об ошибках с указанием позиции неверного символа ## Структура | Файл | Назначение | |-------------------|-------------------------------------| | `calculator.py` | Публичный API (parse_and_eval / try_evaluate) | | `parser.py` | Токенизатор и синтаксический анализатор -> AST | | `nodes.py` | Узлы AST + рекурсивный оценщик | | `cli.py` | Интерактивная точка входа (REPL/пакетный режим) | | `test_calculator.py` | Unit-тесты (pytest / unittest) | | `pyproject.toml` | Пакет, entry point `calc`, конфиги ruff/mypy/coverage | | `README.md` | Это | ## Архитектура Конвейер из трёх стадий: `токенизация -> AST -> eval`. Парсер строит dерево узлов (`NumNode`, `BinaryNode`, `PowNode`, `CallNode`, `IdNode`, …), оценщик `Evaluator` вычисляет его в словаре переменных `env` (в CLI там живёт `ans`). Ошибки — одна иерархия `ASTError` (`SyntaxError_`, `DivisionByZeroError`) из `nodes.py`, re-экспортируется через `calculator.py`. ## Установка и запуск ```bash pip install -e . # даёт команду calc calc # REPL calc "2 + 3" # пакетный режим ``` Или без установки: `python cli.py`. ## Разработка ```bash ruff check . # линтер (конфиг в pyproject.toml) mypy calculator.py parser.py nodes.py cli.py pytest --cov test_calculator.py ``` CI (Gitea Actions, `.github/workflows/ci.yml`): lint -> type-check -> test+coverage на каждый push/PR в master. ## Запуск Калькулятор работает на Python 3.10+ (без установки пакетов). ### Интерактивный режим ```bash python cli.py ``` После запуска вводите выражение, построчно: ``` $ python cli.py Калькулятор. Введите выражение, 'выход'/'exit' — для завершения. 2 + 3 * (4 - 1) % 100 6 выход Пока! ``` ### Пакетный режим (аргументы строки выражений) ```bash python cli.py "2 + 2" "(2 + 3) * 4" "1 / 0" "2 ** 10" ``` ``` 4 20 Ошибка: Деление на ноль 1024 ``` ### Выход из цикла `выход` или `exit` (регистронезависимо, допускаются пробелы вокруг). ## Тесты ```bash # через pytest (рекомендуется) python -m pytest test_calculator.py -v # через stdlib unittest python -m unittest test_calculator -v ``` Тесты покрывают: - базовые операции и отрицательные числа; - приоритет операций и скобки (в т.ч. вложенные); - проценты; - деление на ноль (raise + сообщение); - синтаксические ошибки; - правоассоциативность степени; - команды выхода.