Подтвердить что ты не робот

Целочисленное деление на отрицательное число

Что должно возвращать целое деление -1/5? Я совершенно смущен этим поведением. Я думаю, что математически это должно быть 0, но python и ruby ​​возвращают -1.

Почему здесь разные языки ведут себя по-другому? Пожалуйста, объясните кому-нибудь. Спасибо.

| Language  | Code           | Result |
|-----------+----------------+--------|
| ruby      | -1 / 5         |     -1 |
| python    | -1 / 5         |     -1 |
| c         | -1 / 5         |      0 |
| clojure   | (int (/ -1 5)) |      0 |
| emacslisp | (/ -1 5)       |      0 |
| bash      | expr -1 / 5    |      0 |
4b9b3361

Ответ 1

Короткий ответ: Дизайнеры языка выбирают, будет ли их язык округлять до нуля, отрицательной бесконечности или положительной бесконечности при выполнении целочисленного деления. Различные языки сделали разные варианты.

Длинный ответ: Авторы языка Python и Ruby решили, что округление до отрицательной бесконечности имеет больше смысла, чем округление к нулю (например, C). Создатель python написал сообщение в блоге о своих рассуждениях здесь. Я вычитал большую часть этого ниже.

Сегодня меня спросили (снова), чтобы объяснить, почему целочисленное деление в Python возвращает пол результата вместо усечения в нуль, как C.

Для положительных чисел нет ничего удивительного:

>>> 5//2
2

Но если один из операндов отрицательный, результат перекрывается, т.е. округляется от нуля (к отрицательной бесконечности):

>>> -5//2
-3
>>> 5//-2
-3

Это беспокоит некоторых людей, но есть хорошая математическая причина. Операция целочисленного деления (//) и ее родство, по модулю (%), идти вместе и удовлетворять хорошим математическим (все переменные являются целыми):

a/b = q with remainder r

такое, что

b*q + r = a and 0 <= r < b
(assuming a and b are >= 0).

Если вы хотите, чтобы соотношение расширялось для отрицательного a (сохранение b положительный), у вас есть два варианта: если вы усекаете q до нуля, r станет отрицательным, так что инвариант изменится на 0 <= abs (r) в противном случае вы можете выполнить q до отрицательной бесконечности, а инвариантное остается 0 <= r < б. [update: fixed this para]

В математической теории чисел математики всегда предпочитают последнее (см., например, Wikipedia). Для Python я сделал тот же выбор потому что есть некоторые интересные приложения по модулю где знак a неинтересен. Рассмотрите возможность принятия Временная метка POSIX (секунды с начала 1970 года) и превращение ее в время суток. Поскольку 24 * 3600 = 86400 секунд в день, это вычисление просто t% 86400. Но если бы мы хотели выразить время до 1970 года с использованием отрицательных чисел правило "обрезать к нулю" даст бессмысленный результат! Используя правило пола, все работает хорошо.

Ответ 2

Целочисленное деление зависит от реализации. Из Википедии по модулю операции:

Во многих реализациях используется усеченное деление, где частное определяется как усечение q= trunc (a/n), другими словами, это первое целое число в направлении 0 от точного рационального частного, а остальное - как r= a - n q, Неформально говоря, частное "округляется до нуля", и поэтому остаток имеет тот же знак, что и дивиденд.

Кнут описал деление по этажам, где частное определяется функцией пола q= floor (a/n), а остаток r равен

r = a - nq = a - n \left\lfloor {a \over n} \right\rfloor.

Здесь частное всегда округляется вниз (даже если оно уже отрицательно), а остаток имеет тот же знак, что и делитель.