Работа модуля с отрицательными значениями - странная вещь?
Не могли бы вы рассказать мне, сколько стоит (-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. Я не считаю, что это должно быть очень зависимым от платформы, но я видел незнакомые вещи.
Ответ 8
Это действительно 3. В модульной арифметике модуль - это просто остаток деления, а остаток от -2, деленный на 5 равно 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 - это ложная оптимизация, по крайней мере, в эти дни. Хороший компилятор, вероятно, сможет использовать эквивалентность для оптимизации везде, где отрицательное число не может произойти (и почти наверняка, если вы используете неподписанные типы). С другой стороны, когда могут возникать отрицательные числа, вы почти наверняка заботитесь о деталях - по соображениям переносимости вы должны использовать очень тщательно разработанные сверхкомплексные алгоритмы и/или проверки, чтобы обеспечить получение результатов, которые вы хотите, независимо от округления и остатка поведение.
Другими словами, выигрыш для этой "оптимизации" в большинстве случаев (если не всегда) является иллюзией, в то время как в некоторых случаях очень реальные затраты - так это ложная оптимизация.