Поведение оператора % с отрицательными числами в Python

Поведение оператора % с отрицательными числами в Python

@python_quiz

Разберем этот квиз

Коротко: выражения

python

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

Исходный код квиза

python

Результаты (быстро)

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

Правило и формула

В Python остаток определяется так:
a % b = a - b * (a // b)

Здесь // — это целочисленное деление с округлением вниз (floor division). Из-за этого поведение при отрицательных числах отличается от простого "остаток = абс(a) % абс(b)". Важное следствие: знак остатка совпадает со знаком делителя b (или равен нулю).

Также выполняется тождество:
a == b * (a // b) + (a % b)

Пошаговый разбор выражений

1) -3 % 2

  • Сначала вычисляем целочисленное деление: -3 // 2 = -2 (потому что -3/2 = -1.5, а округление вниз даёт -2).
  • Подставляем в формулу: -3 - 2 * (-2) = -3 + 4 = 1.
  • Итог: остаток = 1 (положительный, как делитель 2).

2) 3 % -2

  • Целочисленное деление: 3 // -2 = -2 (3/(-2) = -1.5, floor = -2).
  • Подстановка: 3 - (-2) * (-2) = 3 - 4 = -1.
  • Итог: остаток = -1 (отрицательный, как делитель -2).

3) -3 % -2

  • Целочисленное деление: -3 // -2 = 1 (-3/(-2) = 1.5, floor = 1).
  • Подстановка: -3 - (-2) * 1 = -3 + 2 = -1.
  • Итог: остаток = -1 (отрицательный, как делитель -2).

Подтверждение в коде

python

Ожидаемый вывод:

Частые заблуждения и заметки

  • Многие ожидают, что остаток при делении сохраняет знак делимого (a). В Python знак остатка следует знаку делителя (b).
  • Поведение может отличаться в других языках (например, некоторые языки используют усечение к нулю при делении, из‑за чего знак остатка совпадает с делимым). Поэтому при переносе алгоритмов между языками на это стоит обратить внимание.
  • Утверждение a % b == a - b * (a // b) — надёжный способ предсказать значение в Python.

Вывод

Оператор % в Python даёт такой остаток, что выполняется равенство a == b * (a // b) + (a % b), а // — это floor division (округление вниз). Следствие: знак остатка совпадает со знаком делителя b. Для данных выражений это даёт последовательность результатов: положительный, затем отрицательный и снова отрицательный.

Report Page