C и Python - другое поведение по модулю (%) операция

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

В Python:

-1 % 10

производит 9

В C это производит-1!

  1. Какой является правом по модулю?
  2. Как сделать ультрасовременную операцию в C, чтобы быть тем же как в Python?
63
задан Cristian Ciupitu 7 May 2018 в 21:16
поделиться

4 ответа

  1. Оба варианта верны, однако в математике (число теории, в частности), Python ' Наиболее часто используется s по модулю .
  2. В C вы выполняете ((n% M) + M)% M , чтобы получить тот же результат, что и в Python. E. g. ((- 1% 10) + 10)% 10 . Обратите внимание, как это все еще работает для положительных целых чисел: ((17% 10) + 10)% 10 == 17% 10 , а также для обоих вариантов реализации C (положительный или отрицательный остаток).
69
ответ дан 24 November 2019 в 16:20
поделиться

Python имеет "истинную" операцию по модулю, тогда как C имеет операцию остатка .

Он имеет прямое отношение к тому, как обрабатывается отрицательное целочисленное деление, т. Е. округляется до 0 или до бесконечности. Python округляется в сторону минус бесконечности, а C (99) - в сторону 0, но на обоих языках (n / m) * m + n% m == n , поэтому оператор% должен выполнять компенсацию в правильном направлении.

Ада более ясна и имеет и то, и другое, например mod и rem .

30
ответ дан 24 November 2019 в 16:20
поделиться

В C89 / 90 поведение оператора деления и оператора остатка с отрицательными операндами определяется реализацией , что означает, что в зависимости от реализации вы можете получить любое поведение. Просто требуется, чтобы операторы согласовывались друг с другом: из a / b = q и a% b = r следует a = b * q + r . Используйте статические утверждения в своем коде, чтобы проверить поведение, если оно критически зависит от результата.

В C99 поведение, которое вы наблюдаете, стало стандартом.

Фактически, любое поведение имеет определенную логику. Поведение Python реализует истинную операцию по модулю. Наблюдаемое вами поведение C соответствует округлению до 0 (это также поведение Fortran).

Одна из причин, по которой округление в сторону 0 является предпочтительным в C, заключается в том, что вполне естественно ожидать, что результат -a / b будет таким же, как - (a / b) . В случае истинного поведения по модулю -1% 10 будет оцениваться как 9, что означает, что -1 / 10 должно быть -1. Это может показаться довольно неестественным, поскольку - (1/10) равно 0.

15
ответ дан 24 November 2019 в 16:20
поделиться

Оба ответа верны, поскольку -1 по модулю 10 совпадает с 9 по модулю 10 .

r = (a mod m)
a = n*q + r

Вы можете быть уверены, что | r | <| n | , но не то, что значение r . Есть 2 ответа, отрицательный и положительный.


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

Если вы хотите получить положительный ответ, вы можете просто добавить 10, если считаете, что ваш ответ отрицательный.

Чтобы оператор по модулю работал одинаково на всех языках, просто помните, что:

n mod M == (n + M) mod M

и в целом:

n mod M == (n + X * M) mod M
4
ответ дан 24 November 2019 в 16:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: