В чем разница между «модом» и «остатком»?


134

Мой друг сказал, что между «модом» и «остатком» есть различия.

Если да, то каковы эти различия в C и C ++? Означает ли '%' в C либо "mod", либо "rem"?


2
Вероятно, это неверно определено для отрицательных операндов.
Василий Старынкевич

1
Я не C :( так что не могу ответить на этот вопрос в поле для ответа. Но, пожалуйста, взгляните на эту статью :)
bonCodigo

1
% - остаток. Подробности ответа здесь -> blogs.msdn.com/b/ericlippert/archive/2011/12/05/…
wim

1
Вопрос ничего не значит, пока вы точно не определите, что означают эти термины.
Дэвид Хеффернан

14
@ Дэвид: вопрос в значениях терминов. Если вы говорите, что вопрос не имеет смысла, несмотря на то, что несколько человек понимают его так, как задумывал задающий вопрос, тогда, я думаю, вам следует уточнить, что вы имеете в виду под словом «значит» ;-)
Стив Джессоп

Ответы:


140

Есть разница между модулем и остатком. Например:

-21мод 4это 3потому , что -21 + 4 x 6есть 3.

Но -21деление 4дает -5с остатком -1.

Для положительных значений разницы нет.


22
% означает rem в C.
banuj 03

22
@Jinxiao: в C89 он был определен реализацией: %всегда был остатком, но он также мог быть модулем (т.е. всегда положительным), потому что в C89 целочисленное деление разрешалось округлять в сторону отрицательной бесконечности, а не в сторону 0. Итак, в C89, -5 / 2может быть -2с остатком -1или -3с остатком 1, реализация просто должна задокументировать который. C99 убрал гибкость, теперь -5 / 2всегда -2.
Стив Джессоп,

2
Собственно, что такое модуль, непонятно. Кажется, есть много разных определений, в зависимости от контекста и языка. См. Статью в Википедии о modulo_operation. В некоторых контекстах это фактически то же самое, что и остаток.
Rudy Velthuis

9
Может кто-нибудь объяснить этапы первого расчета? Как -21мода 4это 3? Почему расчет -21 + 4 x 6?
Оз Эдри

13
@OzEdri Чтобы получить какое-то число по модулю 4, вы добавляете любое целое число, кратное 4, необходимое для получения числа от 0 до 3. Для -21 это целое число равно 6, потому что оно -21 + 4 x 6находится между 0 и 3.
Дэвид Шварц,

47

Означает ли '%' в C либо "mod", либо "rem"?

В C %- остаток 1 .

..., результатом /оператора является алгебраическое частное с отброшенной дробной частью ... (Это часто называется "усечением до нуля".) C11dr §6.5.5 6

Операнды %оператора должны иметь целочисленный тип. C11dr §6.5.5 2

Результатом /оператора является частное от деления первого операнда на второй; результат %оператора - остаток ... C11dr §6.5.5 5


В чем разница между «модом» и «остатком»?

C не определяет «модуль», такой как целочисленная функция модуля, используемая в евклидовом делении или другом модуле . «Евклидова мода» отличается от a%bоперации C, когда aона отрицательна.

 // a % b
 7 %  3 -->  1  
 7 % -3 -->  1  
-7 %  3 --> -1  
-7 % -3 --> -1   

По модулю как евклидово деление

 7 modulo  3 -->  1  
 7 modulo -3 -->  1  
-7 modulo  3 -->  2  
-7 modulo -3 -->  2   

Код кандидата по модулю:

int modulo_Euclidean(int a, int b) {
  int m = a % b;
  if (m < 0) {
    // m += (b < 0) ? -b : b; // avoid this form: it is UB when b == INT_MIN
    m = (b < 0) ? m - b : m + b;
  }
  return m;
}

Примечание о числах с плавающей запятой: double fmod(double x, double y)хотя и называется "fmod", это не то же самое, что евклидово деление "mod", но похоже на целочисленный остаток C:

Эти fmod функции вычисления с плавающей точкой остаток x/y. C11dr §7.12.10.1 2

fmod( 7,  3) -->  1.0  
fmod( 7, -3) -->  1.0  
fmod(-7,  3) --> -1.0  
fmod(-7, -3) --> -1.0   

Устранение неоднозначности : C также имеет аналогичную именованную функцию, double modf(double value, double *iptr)которая разбивает значение аргумента на целые и дробные части, каждая из которых имеет тот же тип и знак, что и аргумент. Это не имеет ничего общего с обсуждением «мода» здесь, за исключением сходства имен.


1 До C99 определение C все %еще было остатком от деления, но затем /позволяло округлять отрицательные частные, а не «усечение до нуля». См. Почему вы получаете разные значения для целочисленного деления в C89? , Таким образом, при некоторой компиляции до C99 %код может действовать точно так же, как «мод» евклидова деления. Вышеупомянутое modulo_Euclidean()будет работать и с этим альтернативным остатком старой школы.


1
Чтобы реализовать евклидово деление и функции по модулю в C, см. Раздел «Деление и модуль для компьютерных ученых» . Он может работать быстрее, если вы знаете, что только ваш дивиденд может быть отрицательным, но ваш делитель всегда положителен: godbolt.org/g/63UqJo . Связанный: вопрос о x86 asm с просьбой о неотрицательном модуле
Питер Кордес

Обычное определение оператора по модулю больше похоже:
Майк Хаски,

2

Модуль, в модульной арифметике, как вы говорите, - это значение, оставшееся или оставшееся значение после арифметического деления. Это обычно известно как остаток. % формально является оператором остатка в C / C ++. Пример:

7 % 3 = 1  // dividend % divisor = remainder

Осталось обсудить, как обрабатывать отрицательные входные данные для этой операции%. Современные C и C ++ создают значение остатка со знаком для этой операции, где знак результата всегда совпадает с вводом делимого, независимо от знака ввода делителя.


1

В C, C ++ и многих языках %остаток НЕ является оператором модуля.

Например, в операции -21 / 4целая часть -5и десятичная часть -.25. Остаток - это дробная часть, умноженная на делитель, поэтому наш остаток равен -1. JavaScript использует оператор остатка и подтверждает это

console.log(-21 % 4 == -1);

Оператор модуля похож на «часы». Представьте себе круг со значениями 0, 1, 2 и 3 в положениях 12 часов, 3 часов, 6 часов и 9 часов соответственно. Переход по часовой стрелке на частное по часовой стрелке приводит нас к результату нашей операции модуля или, в нашем примере с отрицательным частным, против часовой стрелки, что дает 3.

Примечание. Модуль всегда имеет тот же знак, что и делитель, а остаток - тот же знак, что и частное. Добавление делителя и остатка, когда хотя бы один остаток отрицательный, дает модуль.


-2

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

 7 modulo  3 -->  1  
 7 modulo -3 --> -2 
-7 modulo  3 -->  2  
-7 modulo -3 --> -1 

2
Подразделение вики евклидовой утверждает , 0 ≤ r < |b|что означает остаток ака «операции по модулю.» всегда как минимум 0. Какое определение вы используете, чтобы получить значения -2 и -1?
chux

сэр, я не знаю, но я просто погуглил 7 по модулю -3 -> -2. и-7 по модулю -3 -> -1, пожалуйста, объясните, сэр, почему это произошло
shub sharma

1
Google использует другое определение модуля (знаковый модуль?), Чем Евклидово деление в Wiki (как описано Раймондом Т. Баутом). Здесь больше обсуждаются различия. Мораль рассказа: a%bи a modulo bиметь то же значение, когда a,bпозитивны. C99 определяет %точно с отрицательными значениями. C называет это «остатком». «Modulo» имеет различные определения в мире, касающиеся отрицательных значений.
Спецификация
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.