Работа модуля с отрицательными значениями - странная вещь?

Не могли бы вы рассказать мне, сколько стоит (-2) % 5? Согласно моему интерпретатору Python, 3, но есть ли у вас мудрые объяснения?

Я читал, что на некоторых языках результат может быть зависящим от машины, но я не уверен, хотя.

Ответы

Ответ 1

Кстати: большинство языков программирования не согласуются с Python и дают результат -2. В зависимости от интерпретации модуля это правильно. Однако наиболее согласованное математическое определение утверждает, что модуль a и b является (строго положительным) покоем r деления a/b. Точнее, 0 <= r < b по определению.

Ответ 2

Результат работы модуля на негативах, по-видимому, зависит от языка программирования, и вот список http://en.wikipedia.org/wiki/Modulo_operation

Ответ 3

Ваш интерпретатор Python верен. Один (глупый) способ вычисления модуля состоит в вычитании или добавлении модуля до тех пор, пока результирующее значение не будет находиться между 0 и (модуль - 1).

например.: 13 mod 5 = (13 - 5) mod 5 = (13 - 10) mod 5 = 3

или в вашем случае: -2 mod 5 = (-2 + 5) mod 5 = 3

Ответ 4

Как и в документации, в Двоичные арифметические операции, Python гарантирует, что:

Целочисленное деление и модульные операторы связаны следующим тождеством: x == (x/y)*y + (x%y). Целочисленное деление и модуляция также связаны со встроенной функцией divmod(): divmod(x, y) == (x/y, x%y).

И действительно,

>>> divmod(-2, 5)
(-1, 3).

Другим способом визуализации однородности этого метода является вычисление divmod для небольшой последовательности чисел:

>>> for number in xrange(-10, 10):
...     print divmod(number, 5)
...
(-2, 0)
(-2, 1)
(-2, 2)
(-2, 3)
(-2, 4)
(-1, 0)
(-1, 1)
(-1, 2)
(-1, 3)
(-1, 4)
(0, 0)
(0, 1)
(0, 2)
(0, 3)
(0, 4)
(1, 0)
(1, 1)
(1, 2)
(1, 3)
(1, 4)

Ответ 5

Ну, 0% 5 должно быть 0, правильно?

-1% 5 должно быть 4, потому что следующая разрешенная цифра идет в обратном направлении (т.е. она не может быть 5, так как это выходит за пределы диапазона).

И следуя этой логике, -2 должно быть 3.

Самый простой способ подумать о том, как он будет работать, состоит в том, что вы продолжаете добавлять или вычитать 5 до тех пор, пока число не упадет между 0 (включительно) и 5 ​​(исключая).

Я не уверен в зависимости от машины. Я никогда не видел реализации, но я не могу сказать, что это никогда не делалось.

Ответ 6

Как объясняется в других ответах, существует множество вариантов для работы с модулем с отрицательными значениями. В общем, разные языки (и разные архитектуры машин) дадут другой результат.

В соответствии с справочное руководство Python,

Оператор modulo всегда дает результат с тем же знаком, что и его второй операнд (или нуль); абсолютное значение результата строго меньше абсолютного значения второго операнда.

- выбор, выбранный Python. В основном по модулю определяется так, что это всегда выполняется:

x == (x/y)*y + (x%y)

поэтому имеет смысл, что (-2)% 5 = -2 - (-2/5) * 5 = 3

Ответ 7

Ну, -2, разделенный на 5, будет 0 с остатком 3. Я не считаю, что это должно быть очень зависимым от платформы, но я видел незнакомые вещи.

Ответ 9

Результат зависит от языка. Python возвращает знак делителя, где, например, С# возвращает знак дивиденда (т.е. -2% 5 возвращает -2 в С#).

Ответ 10

Одним из объяснений может быть то, что отрицательные числа сохраняются с помощью 2 дополнения. Когда интерпретатор python пытается выполнить операцию modulo, он преобразуется в значение unsigned. Таким образом, вместо выполнения (-2)% 5 он фактически вычисляет 0xFFFF_FFFF_FFFF_FFFD% 5, который равен 3.

Ответ 11

Будьте осторожны, чтобы не полагаться на это поведение мод в C/С++ во всех ОС и архитектурах. Если я правильно помню, я попытался положиться на код C/С++, например

float x2 = x % n;

чтобы сохранить x2 в диапазоне от 0 до n-1, но отрицательные числа заполнились, когда я буду скомпилировать на одной ОС, но все будет хорошо работать в другой ОС. Это было сделано для плохой отладки времени, так как это произошло только в половине случаев!

Ответ 12

Кажется, существует общая путаница между терминами "по модулю" и "остатком".

В математике остаток всегда должен быть согласован с частным, так что если a / b == c rem d then (c * b) + d == a. В зависимости от того, как вы обходите свой фактор, вы получаете разные остатки.

Однако modulo всегда должен давать результат 0 <= r < divisor, который согласуется с делением round-to-minus-infinity, если вы разрешаете отрицательные целые числа. Если деление округляется к нулю (что является общим), то по модулю и остатку они эквивалентны только для неотрицательных значений.

Некоторые языки (в частности, C и С++) не определяют требуемое поведение округления/остатка, а % неоднозначно. Многие определяют округление по отношению к нулю, но используют термин по модулю, где остаток будет более правильным. Python относительно необычен тем, что он округляется до отрицательной бесконечности, поэтому по модулю и остатку эквивалентны.

Ада округляется к нулю IIRC, но имеет как mod, так и rem.

Политика C предназначена для того, чтобы компиляторы могли выбрать наиболее эффективную реализацию для машины, но IMO - это ложная оптимизация, по крайней мере, в эти дни. Хороший компилятор, вероятно, сможет использовать эквивалентность для оптимизации везде, где отрицательное число не может произойти (и почти наверняка, если вы используете неподписанные типы). С другой стороны, когда могут возникать отрицательные числа, вы почти наверняка заботитесь о деталях - по соображениям переносимости вы должны использовать очень тщательно разработанные сверхкомплексные алгоритмы и/или проверки, чтобы обеспечить получение результатов, которые вы хотите, независимо от округления и остатка поведение.

Другими словами, выигрыш для этой "оптимизации" в большинстве случаев (если не всегда) является иллюзией, в то время как в некоторых случаях очень реальные затраты - так это ложная оптимизация.