Я обнаружил странное поведение в Python относительно отрицательных чисел:
>>> -5 % 4
3
Может ли кто-нибудь объяснить, что происходит?
Я обнаружил странное поведение в Python относительно отрицательных чисел:
>>> -5 % 4
3
Может ли кто-нибудь объяснить, что происходит?
..., -9, -5, -1, 3, 7, ...
math.fmod
для получения того же поведения, что и в C или Java.Ответы:
В отличие от C или C ++, оператор Python по модулю (
%
) всегда возвращает число, имеющее тот же знак, что и знаменатель (делитель). Ваше выражение дает 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, чтобы узнать, как определяется знак результата для разных языков.)
источник
Вот объяснение от Гвидо ван Россума:
http://python-history.blogspot.com/2010/08/why-pythons-integer-division-floors.html
По сути, это так, что a / b = q с остатком r сохраняет отношения b * q + r = a и 0 <= r <b.
источник
a
и положительноеb
, тогда как Python - нижние. Это всегда правдаabs(r) < b
, и если и только еслиr <= 0
.Не существует лучшего способа обработки целочисленного деления и модов с отрицательными числами. Было бы неплохо, если бы
a/b
была такая же величина и противоположный знак(-a)/b
. Было бы неплохо, если быa % b
действительно был по модулю b. Поскольку мы очень хотимa == (a/b)*b + a%b
, первые два несовместимы.Какой из них оставить - вопрос сложный, и есть аргументы для обеих сторон. C и 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
%
всегда выводит ноль или положительный результат *//
всегда округляется до отрицательной бесконечности* ... пока правильный операнд положительный. С другой стороны
11 % -10 == -9
источник
В Python оператор по модулю работает следующим образом.
>>> mod = n - math.floor(n/base) * base
так что результат (для вашего случая):
mod = -5 - floor(-1.25) * 4 mod = -5 - (-2*4) mod = 3
в то время как другие языки, такие как C, JAVA, JavaScript, используют усечение вместо пола.
>>> mod = n - int(n/base) * base
что приводит к:
mod = -5 - int(-1.25) * 4 mod = -5 - (-1*4) mod = -1
Если вам нужна дополнительная информация об округлении в python, прочтите это .
источник
По модулю, классы эквивалентности для 4:
Вот ссылка на поведение по модулю с отрицательными числами . (Да, я погуглил)
источник
Я тоже подумал, что это странное поведение Python. Оказывается, я плохо решал деление (на бумаге); Я давал значение 0 частному и значение -5 для остатка. Ужасно ... Я забыл геометрическое представление целых чисел. Вспомнив геометрию целых чисел, заданных числовой линией, можно получить правильные значения частного и остатка и проверить правильность поведения Python. (Хотя предполагаю, что вы уже давно решили свою проблему).
источник
Также стоит упомянуть, что разделение в python отличается от C: рассмотрим
>>> x = -10 >>> y = 37
в C вы ожидаете результата
0
что такое x / y в питоне?
>>> print x/y -1
а% - по модулю, а не остаток! В то время как x% y в C дает
-10
питон дает.
>>> 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, плюс избегает условных операторов.
источник