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

Результат -1% 7 отличается в javascript (-1) и python (6)

Выражение -1 % 7 в JavaScript дает мне -1 в качестве результата. Если в Python и Haskell я нашел результат 6.

Может ли кто-нибудь объяснить, почему у обоих разные виды поведения? Какой из них правильный?

4b9b3361

Ответ 1

Я дам немного другой ответ. Как говорили другие, функции могут выполнять все, что вы их определяете, и m - x = -x mod m. В качестве прелюдии я отмечу, что у Haskell есть две "mod" функции, mod и rem, которые отличаются только этим аспектом. Вы можете сделать случай, когда mod предпочтительнее математически. rem соответствует тому, что вы получите на процессоре x86. Существует, по сути, третья, евклидова, которая может быть даже лучше, а также описана Раймондом Бутом в Евклидовы определения функций Div и Mod. Третья форма всегда возвращает положительный модуль. (Есть, по сути, как минимум два других варианта, которые можно сделать.)

Итак, определение Javascript - это то, что вы получаете от большинства кодов операций mod. В этом смысле это может быть предпочтительнее, поскольку это сделает его более эффективным для реализации. Математически определение Haskell и Python лучше, чем Javascript. Также есть третье определение, которое может быть немного лучше.

Одно ключевое свойство, которое обе имеют определения Евклида и Хаскелла/Питона, равно x mod m = y mod m, эквивалентно x = y mod m, в котором отсутствует определение Javascript. Вы можете проверить, вычислив 6 % 7 в Javascript.

Ответ 2

Оба правильные, они просто используют разные соглашения относительно обработки отрицательных операндов. Для положительных чисел соглашения совпадают, а для отрицательных чисел - нет. В Python a % b всегда имеет тот же знак, что и b.

В дальнейшем я буду использовать нотацию Python, где // используется для целочисленного деления.

Пусть

q, r  = a // b, a % b

Тогда

a == q * b + r

должен быть истинным на любом языке (при условии, что a и b являются целыми числами, причем b не равно нулю). Таким образом, способ обработки остатка должен соответствовать соглашению, используемому для целочисленного деления. В Python целочисленное деление - это разделение полов, т.е. Результат округляется до отрицательной бесконечности. В некоторых других языках используется округление к нулю. И на некоторых языках вы получаете любое соглашение, которое разработчик ЦП решил реализовать, поэтому один и тот же код, выполняемый на другом оборудовании, может дать разные результаты. Как вы можете себе представить, это может быть несколько раздражающим.:)

Ответ 3

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

Вы можете просто добавить модуль в свою переменную, чтобы получить положительное число, или проверить, является ли это число положительным или отрицательным, прежде чем выполнять операцию модуля и исправить результат после переключения между ними.


Псевдокод для преобразования a%b между двумя:

На языке, где -1%7 == -1, вы делаете это, чтобы получить положительное число:

((a%b)+b) % b

И на языке, где -1%7 == 6 вы можете сделать это, чтобы получить подписанную версию:

if a < 0:
  return (a%b)-b
else:
  return a%b

Ответ 4

Оба правильные.

Чтобы выполнить другие ответы, вы также можете рассмотреть функцию divmod в Python:

Возьмите два (не сложных) числа в качестве аргументов и верните пару чисел, состоящих из их частного и остального при использовании целочисленного деления. Со смешанными типами операндов применяются правила для двоичных арифметических операторов. Для целых чисел результат будет таким же, как (a // b, a % b). Для чисел с плавающей запятой результат (q, a % b), где q обычно math.floor(a / b), но может быть на 1 меньше этого. В любом случае q * b + a % b очень близко к a, если a % b отличен от нуля, он имеет тот же знак, что и b, и 0 <= abs(a % b) < abs(b).

>>> divmod(-1, 7)
(-1, 6)

Ответ 5

% обозначает разные операторы в JavaScript и в Python.

В JavaScript % выступает оператор Remainder. В документации уже указано различие между оставшимся и модульным операциями:

Оператор остатка возвращает оставшийся остаток, когда один операнд делится на второй операнд. Он всегда принимает знак дивиденда, а не делитель. Он использует встроенную функцию modulo для получения результата, который является целым остатком деления var1 на var2 - например, - var1 modulo var2. Существует предложение получить фактический модуль-оператор в будущей версии ECMAScript, , разница в том, что результат по модулю оператора будет принимать знак делителя, а не дивиденд.

(Подчеркнуто мной)

В отличие от этого: в Python % обозначает оператор modulo. В документации также делается выражение о знаке:

Оператор % (modulo) возвращает остаток от деления первого аргумента на второй. Числовые аргументы сначала преобразуются в общий тип. Аргумент zero right вызывает исключение ZeroDivisionError. [...] Оператор modulo всегда дает результат с тем же знаком, что и его второй операнд (или ноль); абсолютное значение результата строго меньше абсолютного значения второго операнда [2].

(Подчеркнуто мной)