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

StackOverflow https://stackoverflow.com/questions/43775

  •  09-06-2019
  •  | 
  •  

Вопрос

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

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

Это было полезно?

Решение

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

Другие советы

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

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

например ,:13 мод 5 = (13 − 5) мод 5 = (13 - 10) мод 5 = 3

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

Как сказано в документации в Двоичные арифметические операции, 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)

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

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

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

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

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

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

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

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

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

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

таким образом, имеет смысл, что (-2)%5 = -2 - (-2/5)*5 = 3

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

Это действительно 3.В модульная арифметика, модуль - это просто остаток от деления, а остаток от -2, деленный на 5, равен 3.

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

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

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

float x2 = x % n;

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

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

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

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

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

Ada округляет значение IIRC до нуля, но имеет оба mod и rem операторы.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top