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

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

@python_quiz

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

У нас есть короткая программа:

python

Разберём, что она делает и почему.

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

Запуск этого кода печатает:

python

Ключевая идея: в Python результат операции a % b всегда имеет тот же знак, что и делитель b. При делителе 2 это означает, что остаток будет неотрицательным и лежать в диапазоне [0, 2).

Рассчитаем вручную:

  • -3 % 2 → floor(-3/2) = -2, остаток = -3 - (-2)*2 = 1
  • -2 % 2 → 0
  • -1 % 2 → 1
  • 0 % 2 → 0
  • 1 % 2 → 1
  • 2 % 2 → 0
  • 3 % 2 → 1

Разбор вариантов ответов (логика)

  • Варианты, где отрицательные числа дают отрицательный остаток (например, -1), не учитывают правило Python о знаке остатка и потому неверны для этой реализации.
  • Варианты, утверждающие ошибку при вычислении -3 % 2, неверны: оператор % поддерживает отрицательные аргументы и ошибок не вызывает.
  • Правильный результат — последовательность чередующихся 1 и 0, начиная с 1 для -3, как показано выше.

Математическое объяснение (формула)

В Python действует соотношение:
a % b == a - b * floor(a / b)

Для целых a и положительного b это гарантирует результат в диапазоне [0, b). Это отличается от некоторых других реализаций остатка (например, в C/C++ до стандарта, где знак остатка может следовать знаку делимого при усечении деления к нулю).

Пример:

python

Различия с math.fmod и прочими языками

Если нужна другая семантика (остаток с тем же знаком, что и делимое), можно посмотреть на math.fmod:

python

math.fmod возвращает значение с тем же знаком, что и делимое (поведение, близкое к C fmod). В то время как оператор % в Python следует правилу с полом (floor).

Также учтите: в некоторых языках (C/C++, Java и т.д.) семантика операции остатка может отличаться — часть языков используют усечение к нулю при делении, и из-за этого знак остатка соответствует делимому.

Краткий вывод

  • В Python a % b возвращает остаток, имеющий тот же знак, что и делитель b.
  • Для n % 2 при любом целом n результат всегда 0 или 1.
  • Оператор % корректно работает с отрицательными числами — ошибок не происходит.
  • Если нужен остаток с поведением, где знак следует делимому, используйте math.fmod или аналогичные функции, учитывая их тип (float) и особенности.

Report Page