Skip to content

Глава 2. Числа и вычисления: операторы и расчёт показателей

Задача главы: научиться считать метрики успеваемости — прирост, средний балл, проценты, распределение по аудиториям — и проверять их по порогам и сложным критериям отбора.


2.1 Математические операторы: расчёт метрик

Зачем это нужно. Почти любой показатель в отчёте — это арифметика над колонками выгрузки: прирост баллов между диагностиками, средний балл группы, доля выполненных заданий. Операторы Python повторяют школьную математику, но с одним важным отличием в делении.

// PYTHON_EXECUTOR (Pyodide Wasm)

⚠️ Подводный камень

Оператор / всегда возвращает float — даже когда делится нацело. Traceback не появится, ошибка тихая: в отчёт просто уйдёт «Сдали 25.0 человек».

// PYTHON_EXECUTOR (Pyodide Wasm)
ОшибкаЧто значит для PythonЧеловеческий перевод
— (тихая ошибка)«Результат / — всегда float»Делили целое на целое и ждали целое. Для штучных величин нужен оператор целочисленного деления // (раздел 2.3), для вывода — форматирование :.0f.

Правильный паттерн

// PYTHON_EXECUTOR (Pyodide Wasm)

Пояснение логики: оператор выбирается по смыслу показателя. Штучные объекты — люди, аудитории, комплекты бланков — считаются через //; средние, доли и проценты остаются float. Подробно // разбирается в 2.3.


2.2 Округление: round() и «хвостатые» дроби

Зачем это нужно. Деление регулярно даёт длинную дробь: 83 / 3 = 27.666666666666668. В отчёт такое не поставишь — показатели округляют до одного-двух знаков.

// PYTHON_EXECUTOR (Pyodide Wasm)

Второй аргумент round() — сколько знаков оставить после запятой. Если его не указать, число округлится до целого.

⚠️ Подводный камень

Python округляет не так, как учили в школе. Здесь работает «банковское округление» — к ближайшему чётному, если дробная часть ровно 0.5.

// PYTHON_EXECUTOR (Pyodide Wasm)
ОшибкаЧто значит для PythonЧеловеческий перевод
— (тихая ошибка)«Половина округляется к ближайшему чётному»Не баг, а стандарт: при суммировании тысяч показателей такое округление не завышает итог систематически. Но если методика требует школьного правила «0.5 всегда вверх», round() не подходит.

Вторая ловушка того же семейства — дробные числа хранятся приблизительно, поэтому round() иногда «промахивается» в последнем знаке:

// PYTHON_EXECUTOR (Pyodide Wasm)

Правильный паттерн

Округляйте один раз, на выходе, а не на каждом промежуточном шаге — иначе погрешность накапливается. Для вывода удобнее вообще не звать round(), а форматировать прямо в f-строке:

// PYTHON_EXECUTOR (Pyodide Wasm)

Пояснение логики: :.2f округляет только представление числа при выводе, сама переменная остаётся точной и годится для дальнейших расчётов. Это тот же приём, что в главе 1 с процентом выполнения.


2.3 Деление нацело // и остаток %

Зачем это нужно. Эти два оператора выглядят академической экзотикой ровно до первой организационной задачи: рассадить учеников по аудиториям ППЭ, разложить бланки по комплектам, раздать чётные и нечётные варианты.

// — сколько получилось целых объектов

Отбрасывает дробную часть и отвечает на вопрос «сколько полных штук поместилось».

// PYTHON_EXECUTOR (Pyodide Wasm)

% — что осталось сверх целых

Возвращает остаток. Нужен для «неукомплектованного хвоста» и для циклического распределения.

// PYTHON_EXECUTOR (Pyodide Wasm)

Реальное количество аудиторий считается через оба оператора сразу:

// PYTHON_EXECUTOR (Pyodide Wasm)

Скобка (1 if leftover_students else 0) читается слева направо: «прибавить 1, если остаток есть, иначе 0». Это условие в одну строку — целиком разберём его в главе Условия, здесь достаточно запомнить готовую формулу «полные штуки плюс неполный хвост».

⚠️ Подводный камень

Делитель, пришедший из выгрузки, может оказаться нулём — например, в классе не зарегистрировано ни одного участника.

// PYTHON_EXECUTOR (Pyodide Wasm)
Traceback (most recent call last):
File "report.py", line 2, in <module>
average_score = 450 / students_count
ZeroDivisionError: division by zero
ОшибкаЧто значит для PythonЧеловеческий перевод
ZeroDivisionError«Делить на ноль не определено»В знаменателе оказался 0: пустая группа, никто не явился, колонка не заполнена. Проверяйте делитель до расчёта — полноценно это решается в главе про условия.

2.4 Операторы сравнения: проверка порогов

Зачем это нужно. Каждый критерий в отчёте — «сдал / не сдал», «выше среднего», «высокобалльник» — это сравнение с порогом. Результат сравнения всегда bool: True или False.

ОператорЗначениеПример из аналитики
==равноgrade == 5 — отметка ровно «пять»
!=не равноstatus != 'absent' — ученик не отсутствовал
> / <строго больше / меньшеscore > 24 — балл строго выше порога
>= / <=больше или равно / меньше или равноscore >= 80 — от 80 и выше, высокобалльник
// PYTHON_EXECUTOR (Pyodide Wasm)

Отдельная приятная особенность Python: двойные неравенства пишутся так же, как в математике.

// PYTHON_EXECUTOR (Pyodide Wasm)

⚠️ Подводный камень

Порог «не ниже 36» — это >=, а не >. Ошибка в одном символе отправляет в неуспевающие всех, кто набрал ровно проходной балл: на большой выгрузке это десятки человек, и заметить это по итоговой цифре почти невозможно.

Вторая частая ловушка — сравнение балла, который забыли привести к числу после input():

// PYTHON_EXECUTOR (Pyodide Wasm)
Traceback (most recent call last):
File "report.py", line 2, in <module>
print(score > 36)
TypeError: '>' not supported between instances of 'str' and 'int'
ОшибкаЧто значит для PythonЧеловеческий перевод
TypeError«Не знаю, как сравнить текст с числом»Забыли int() вокруг input(). Правило главы 1 работает и здесь: приводите тип в момент ввода.

Правильный паттерн

// PYTHON_EXECUTOR (Pyodide Wasm)

Пояснение логики: приведение типа стоит в момент ввода, поэтому сравнение работает с числами. Порог живёт в отдельной переменной — если методика поменяет проходной балл, правка будет в одной строке. Результат сравнения сохранён в is_passed с говорящим именем: такую переменную дальше можно и напечатать, и передать в расчёт.


2.5 Логические операторы: and, or, not

Зачем это нужно. Реальные критерии почти никогда не состоят из одного условия: медаль, грант, допуск к сессии — это связки из нескольких порогов.

and — строгий отбор: нужны все условия сразу

// PYTHON_EXECUTOR (Pyodide Wasm)

or — мягкий отбор: достаточно любого условия

// PYTHON_EXECUTOR (Pyodide Wasm)

not — инверсия: переворачивает значение

// PYTHON_EXECUTOR (Pyodide Wasm)

⚠️ Подводный камень

and «сильнее» or — он вычисляется первым, как умножение перед сложением. Без скобок смысл критерия меняется незаметно:

// PYTHON_EXECUTOR (Pyodide Wasm)
ОшибкаЧто значит для PythonЧеловеческий перевод
— (тихая ошибка)«Сначала связываю and, потом or»Условие прочиталось как is_olympiad_winner or (ege_math > 80 and ege_rus > 90) — совсем не то, что задумано. Ставьте скобки всегда, когда в критерии есть и and, и or.

Правильный паттерн

// PYTHON_EXECUTOR (Pyodide Wasm)

Пояснение логики: скобки фиксируют порядок и заодно делают критерий читаемым — коллега поймёт его без запуска кода. Длинный критерий лучше сохранять в переменную с говорящим именем (is_grant_eligible, is_allowed), а не встраивать прямо в print().


2.6 Мини-словарик ошибок второй главы

ОшибкаЧто значит для PythonЧеловеческий перевод
ZeroDivisionError«Деление на ноль не определено»В знаменателе 0: пустая группа или незаполненная колонка выгрузки.
TypeError«> не работает между str и int»Сравниваете результат input() с числом. Оберните ввод в int().
SyntaxError«Не понимаю структуру строки»Написали if grade = 5:. Одинарное = — присваивание, сравнение всегда ==.
— (тихая ошибка)«and вычисляется раньше or»Смешали and и or без скобок — критерий отработал не так, как задумано.
— (тихая ошибка)«Половина округляется к чётному»round(2.5) даёт 2. Помните про банковское округление в методиках расчёта.

Самый частый случай целиком. Сам оператор if разбирается в главе Условия, но корень ошибки — здесь, в разделе 2.4: одинарное = присваивает значение, а сравнивает всегда двойное ==.

// PYTHON_EXECUTOR (Pyodide Wasm)
File "report.py", line 2
if grade = 5:
^^^^^^^^^
SyntaxError: invalid syntax. Maybe you meant '==' or ':=' instead of '='?

Мини-кейс: экспресс-проверка претендента на медаль

Задача: принять баллы ЕГЭ по трём предметам, посчитать сумму и средний балл и проверить условие медали — не менее 70 баллов по каждому предмету.

// PYTHON_EXECUTOR (Pyodide Wasm)

Пример работы при вводе Иванова Анна, 88, 70, 91:

--- ЭКСПРЕСС-ПРОВЕРКА ---
Ученик: Иванова Анна
Русский: 88 | Математика: 70 | Информатика: 91
Сумма баллов: 249
Средний балл: 83.0
Медаль подтверждена (не ниже 70 по всем): True

Что получилось: порог вынесен в переменную min_required — если методика изменится, правку нужно внести в одном месте, а не в трёх сравнениях. Использовано >=, поэтому ученик с ровно 70 баллами по математике медаль сохранил. Средний балл не округлялся заранее: round() не понадобился, форматирование :.1f сделало всё на выводе.


Чек-лист главы

  • Помню, что / всегда возвращает float, даже при делении нацело
  • Округляю показатели один раз, на выводе, и знаю про банковское округление в round()
  • Использую // для подсчёта целых объектов (аудитории, комплекты) и % для остатка и чередования вариантов
  • Различаю > и >= при проверке проходного порога
  • Понимаю, что сравнение возвращает bool, и умею писать двойные неравенства 80 <= score <= 100
  • Собираю сложные критерии через and / or / not и ставлю скобки при их смешивании
  • Узнаю ZeroDivisionError и SyntaxError при = вместо ==
  • Выношу пороги и длинные критерии в переменные с говорящими именами

Дальше: Строки и f-строки