Особенность работы деления с остатком для отрицательных чисел

Python Николай

Что такое остаток от деления?

Сегодня поговорим про очень важную особенность работы деления с остатком для отрицательных чисел в Python. Для начала я бы убедился, что вы точно понимаете, что значит “остаток от деления”. Ответье на вопрос:

Квиз

Чему равно 13 % 5?

Определение остатка от деления

Очень часто, новички ошибаются в таких вопросах. Если вы ответили 6, то вероятно вы перепутали остаток от дробной части. Все понимают, что 135=2.6\frac{13}{5}=2.6 и по ошибке думают, что 0.60.6 относится к остатку от деления. На деле 0.60.6 это дробная часть. Давайте поделим 13 на 5 в столбик:

13103
52
13 ÷ 5 = 2, остаток 3

Мы получаем 2 - это целая часть от деления и 3 - остаток от деления. Согласны, что 13=52+313 = 5 * 2 + 3? То есть, чтобы получить исходное число мы должны делитель умножить на частное от деления и прибавить остаток от деления. Это можно записать вот такой формулой:

a=bc+da = b * c + d, где aa - делимое, bb - делитель, cc - частное, dd - остаток

Разбираемся с делением отрицательных чисел

Что будет если мы добавим минус к числу и поделить опять?

13103
5−2
-13 ÷ 5 = -2, остаток -3

На всякий случай проговорю. Мы берем частное именно -2, потому что нам надо 13(10)=3-13 - (-10) = -3, если бы частное было 2, то 1310=23-13 - 10 = -23

Получаем целую часть и остаток такие же, но с минусом. Все вроде логично. Теперь перейдем к Python.

В этом языке программирования есть 3 разных деления: / - обычное, // - целочисленное, % - с остатком. Так вот, весь нюанс с остатками завязан на работе целочисленного деления.

Все дело в том, что когда мы делим целочисленно, Python округляет результат в меньшую сторону. Логично звучит, 13 // 5 = 2 (135=2.6\frac{13}{5}=2.6 -> в меньшую =2= 2).

-4-3-2-10−2.6

А теперь давайте -13 разделим целочисленно.

Квиз

Чему равно -13 // 5?

Если вы правильно ответили, молодцы. Давайте разберемся почему именно такой ответ. Давайте проследим 135=2.6\frac{-13}{5}=-2.6 -> в меньшую будет 33. (влево по числовой прямой, -2 будет больше чем -2,6) Окей, это понятно, а причем тут тогда деление с остатком? Вернемся к формуле и подставим туда значения:

13=5(3)+d-13 = 5 * (-3) + d

Что нужно прибавить к -15, чтобы получить -13? Правильно, 2. Поэтому в Python -13 % 5 = 2, а не -3, как в школьной математике.

Можете сами убедиться, запустив программу ниже

Где это важно?

Особенно важно это в задании 17 (и может даже в 9, ведь есть некоторые прототипы с отрицательными числа. Так же не исключаю вариат, что в каком-то другом задании может пригодиться). Если мы хотим узнать, на какую цифру(ы) оканчивается число. Все знают, что если поделить число с остатком на 10, то мы получим его последнюю цифру (по факту мы получим последнюю цифру в 10 СИСТЕМЕ СЧИСЛЕНИЯ, если поделить с остатком на 2, то мы получим последнюю цифру в 2 СИСТЕМЕ СЧИСЛЕНИЯ и т.д). И к примеру, если мы делим -123 % 10, мы ожидаем, что число оканчивается на 3, но мы получаем вместо 3 (или -3) цифру 7.

Поэтому, держим в голове, что если мы хотим проверить на какую цифру(ы) оканчивается число, нужно делить его по модулю, то есть abs(-123) % 10. Именно модуль числа, а не модуль всего выражения! Ошибкой будет писать так: abs(-123 % 10). Потому что -123 % 10 в Python даст 7. Какая разница нам, если мы будем брать модуль всего результата, 7 и abs(7) эквиваленты. Поэтому убираем минус только у самого числа: abs(-123) % 10

И на всякий случай: проверка кратности не нуждается в модуле. То есть, если мы хотим проверить, что число -123 кратно 3, нам не нужно брать модуль, мы в любом случае получим остаток, равный нулю если кратно, и не ноль в противном случае

Почему так сделали?

Назло математикам? На самом деле, определений остатка несколько. Первое, что мы знаем из школьного курса. Второе, это определение по формуле a=bc+da = b * c + d, где 0d<b0 \leq d < |b|, то есть остаток всегда положительный и не равен делителю. В языках C/C++, Java, C#, Pascal используется первое определение остатка, тогда как в Python Гвидо Ван Россум сознательно выбрал второе определение остатка, потому что посчитал его более правильным: например, a % b всегда даёт результат в диапазоне [0, b) при положительном b, что полезно для циклических индексов, хеширования, работы с днями недели и т.д.

Закрепление материала

Допишите условие так, чтобы программа выводила “Да”, если число n одновременно кратно 3 И оканчивается на цифру 9. Иначе - “Нет”.