Modulo (%) с отрицательными числами в Python
@python_quizРазберем этот квиз
Коротко: поведение оператора % в Python зависит от знака делителя. На практике это значит, что выражение n % 2 для любого целого n вернёт либо 0, либо 1, даже если n отрицательное.
Исходный код квиза

Что выводит программа

Почему так происходит
В Python правило для остатка можно записать формулой:

Из этой формулы видно, что знак результата совпадает со знаком делителя b (в нашем случае b = 2, положительное), поэтому n % 2 возвращает 0 или 1 даже для отрицательных n.
Примеры по элементам:
- -3 % 2 = -3 - 2 * floor(-3/2) = -3 - 2 * (-2) = 1
- -2 % 2 = 0
- -1 % 2 = 1
Можно явственно вывести промежуточные значения:

Разбор вариантов ответов (логически)
Допустим, в квизе были четыре варианта вывода. Их смысл можно проанализировать так:
- Варианты, где для отрицательных n результат даёт 1 или 0 соответствуют поведению Python при положительном делителе 2.
- Варианты, в которых для некоторых отрицательных n появляются отрицательные остатки (например -1), не соответствуют стандартному поведению оператора % в Python (но могут встречаться в других языках или при других определениях остатка).
Практическая проверка (см. вывод выше) показывает, какой из перечисленных вариантов совпадает с действительным выводом программы.
Вывод — что запомнить
- В Python результат a % b имеет знак делителя b.
- Для делителя 2 это значит, что a % 2 всегда будет 0 или 1 для целых a.
- Если вам нужно поведение "остаток с тем же знаком, что и делимое" (как в некоторых других языках), нужно использовать дополнительные преобразования вручную или другую операцию.
Короткий шпаргалка:
- a % b == a - b * floor(a / b)
- Для b > 0 остаток ∈ [0, b-1]
- Для b < 0 остаток ∈ [b+1, 0]
Этого достаточно, чтобы понять результаты подобных квизов и корректно интерпретировать вывод кода.