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

Что должно возвращать целочисленное деление -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 | 

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

Длинный ответ: авторы языка 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 <b. [обновление: исправлено данное параграф]

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

Целочисленное подразделение является специфичным для реализации. Из операции Modulo в Википедии:

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

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

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

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