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

Операция по модулю отрицательных чисел в Python

Я нашел странное поведение в Python относительно отрицательных чисел:

>>> -5 % 4
3

Кто-нибудь может объяснить, что происходит?

4b9b3361

Ответ 1

В отличие от 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 для определения значения результата для разных языков.)

Ответ 3

Нет никакого лучшего способа обработки целых делений и модов с отрицательными числами. Было бы хорошо, если бы a/b была той же величины и противоположного знака (-a)/b. Было бы неплохо, если бы a % b действительно был модулем b. Поскольку мы действительно хотим a == (a/b)*b + a%b, первые два несовместимы.

Какой из них держать - это сложный вопрос, и есть аргументы для обеих сторон. C и С++ округляются до нуля (так a/b == -((-a)/b)), и, по-видимому, Python этого не делает.

Ответ 4

Как уже указывалось, 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
  • Python % всегда выводит ноль или положительный, когда делитель положительный
  • Python // всегда округляется до отрицательной бесконечности

Ответ 6

Я также подумал, что это странное поведение Python. Оказывается, я плохо разбирался в делении (на бумаге); Я указывал значение 0 для частного и значение -5 для остатка. Ужасно... Я забыл геометрическое представление чисел целых чисел. Напомним, что геометрия целых чисел, заданная числовой строкой, можно получить правильные значения для частного и остального и проверить, что поведение Python в порядке. (Хотя я предполагаю, что вы уже давно решили свою проблему).

Ответ 7

Стоит также отметить, что деление в 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, плюс он избегает условных операторов.