Я нашел странное поведение в Python относительно отрицательных чисел:
>>> -5 % 4
3
Кто-нибудь может объяснить, что происходит?
Я нашел странное поведение в Python относительно отрицательных чисел:
>>> -5 % 4
3
Кто-нибудь может объяснить, что происходит?
В отличие от C или С++, оператор python modulo (%
) всегда возвращает число, имеющее тот же знак, что и знаменатель (делитель). Ваше выражение дает 3, потому что
(- 5)% 4 = (-2 & times; 4 + 3)% 4 = 3.
Он выбирается по поведению C, потому что неотрицательный результат часто более полезен. Примером является вычисление недельных дней. Если сегодня вторник (день № 2), каков день недели N дней раньше? В Python мы можем вычислить с помощью
return (2 - N) % 7
но в C, если N ≥ 3, мы получаем отрицательное число, которое является недопустимым числом, и мы должны вручную исправить его, добавив 7:
int result = (2 - N) % 7;
return result < 0 ? result + 7 : result;
(см. http://en.wikipedia.org/wiki/Modulo_operator для определения значения результата для разных языков.)
Вот объяснение от Guido van Rossum:
http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html
По существу, это так, что a/b = q с остатком r сохраняет отношения b * q + r = a и 0 <= r < б.
Нет никакого лучшего способа обработки целых делений и модов с отрицательными числами. Было бы хорошо, если бы a/b
была той же величины и противоположного знака (-a)/b
. Было бы неплохо, если бы a % b
действительно был модулем b. Поскольку мы действительно хотим a == (a/b)*b + a%b
, первые два несовместимы.
Какой из них держать - это сложный вопрос, и есть аргументы для обеих сторон. C и С++ округляются до нуля (так a/b == -((-a)/b)
), и, по-видимому, Python этого не делает.
Как уже указывалось, Python по модулю делает хорошо обоснованное исключение из соглашений других языков.
Это дает отрицательным числам плавное поведение, особенно при использовании в сочетании с оператором //
целочисленного деления, как часто бывает по модулю %
(как в math. Divmod):
for n in range(-8,8):
print n, n//4, n%4
Производит:
-8 -2 0
-7 -2 1
-6 -2 2
-5 -2 3
-4 -1 0
-3 -1 1
-2 -1 2
-1 -1 3
0 0 0
1 0 1
2 0 2
3 0 3
4 1 0
5 1 1
6 1 2
7 1 3
%
всегда выводит ноль или положительный, когда делитель положительный//
всегда округляется до отрицательной бесконечностиModulo, классы эквивалентности для 4:
Здесь ссылка на по модулю поведения с отрицательными номерами. (Да, я googled это)
Я также подумал, что это странное поведение Python. Оказывается, я плохо разбирался в делении (на бумаге); Я указывал значение 0 для частного и значение -5 для остатка. Ужасно... Я забыл геометрическое представление чисел целых чисел. Напомним, что геометрия целых чисел, заданная числовой строкой, можно получить правильные значения для частного и остального и проверить, что поведение Python в порядке. (Хотя я предполагаю, что вы уже давно решили свою проблему).
Стоит также отметить, что деление в python отличается от C:
>>> x = -10
>>> y = 37
в C ожидаешь результата
0
что такое х/у в питоне?
>>> print x/y
-1
и% это по модулю - не остаток! В то время как х% у в С дает
-10
Python дает.
>>> print x%y
27
Вы можете получить как в C
Отдел:
>>> from math import trunc
>>> d = trunc(float(x)/y)
>>> print d
0
И остаток (используя деление сверху):
>>> r = x - d*y
>>> print r
-10
Этот расчет, возможно, не самый быстрый, но он работает для любых комбинаций знаков x и y, чтобы достичь тех же результатов, что и в C, плюс он избегает условных операторов.