Почему оператор% называется оператором «модуля» вместо оператора «остатка»?

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

assert(-1 % 10 == -1)  //Expecting 9

Поэтому, когда он пришел спросить меня об этом, я сказал ему: «Ну, это имеет смысл. Когда вы делите -1 на 10, вы получаете 0 с оставшимся -1. Однако его аргумент состоял в том, что оператор модуля должен быть истинным для «всегда позитивная» модель. Я провел небольшое исследование и обнаружил, что модуль, на который он ссылался, выглядит следующим образом:

Пусть q целочисленное отношение a и n. Пусть г будет остаток. Затем:

a = n * q + r

ОпределениеI Однако использовалась версия модуля Кнута, которая:

Пусть q будет полом деленного на n. Пусть г будет остаток. Затем:

r = a - n * q

Итак, мой вопрос заключается в том, почему в стандарте FORTRAN (а впоследствии и в стандарте C) оказалось, что оператор модуля усекается до 0? Мне кажется неправильным называть это «модулем», а не «остатком» (в математике ответ действительно должен быть 9). Это связано с тем, как аппаратное обеспечение делает разделение?

Для справки:

Википедия о модулеЗапись MSDN об операторе "модуль"
(Да, я понимаю, что это для VS2003 ... Я застрял с ним в настоящее время. Sadface)Изменения оператора модуляНе принимайте положительный остаток ...

TLDR; Является ли аппаратное обеспечение причиной, по которой оператор модуля усекается до 0?

 Chad La Guardia14 февр. 2012 г., 23:11
Избегать этого не в этом вопрос.
 Henk Holterman14 февр. 2012 г., 22:50
Вы понимаете, что этот вопрос и ссылки полны причин, чтобы избежать по модулю с отрицательными операндами?
 OJFord26 сент. 2014 г., 20:44
@supercat «модуль» и «остаток» имеют по 3 слога. «mod» и «rem» имеют по 1 слогу.
 supercat26 сент. 2014 г., 21:01
@OllieFord: «REM» - это ключевое слово в BASIC, а также, возможно, в некоторых языках, основанных на BASIC, которые служат для введения комментария. Кроме того, некоторые языки используют «%» для представления комментариев. Таким образом, описание «%» как оператора «rem» может вызвать некоторую путаницу.
 supercat19 июн. 2013 г., 23:51
Это действительно называется «модуль» или «мод»? Сколько слогов имеет «мод»? Как насчет "остатка"?

Ответы на вопрос(3)

% является оператором остатка в C и C ++.

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

% оператор определен в C и C ++ сa == (a / b * b) + a % b.

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

Когда усечение сделано к нулю,% является оператором остатка, а знак результата является знаком дивиденда. Когда усечение сделано до минус бесконечности,% является оператором по модулю, а знак результата является знаком делителя.

По причинам, по которым C изменил поведение, определяемое реализацией целочисленного деления в отношении усечения, Дуг Гвин из комитета C сказал:

C99 наложил совместимое с Fortran требование в попытке привлечь больше программистов на Fortran и помочь конвертировать код Fortran в C.

Обоснование C99 говорит относительно усечения до деления с нулевым целым числом:

В Fortran, однако, результат всегда будет обрезаться до нуля, и накладные расходы, по-видимому, приемлемы для сообщества числового программирования. Следовательно, C99 теперь требует аналогичного поведения, что должно облегчить перенос кода с Fortran на C.

Вgcc поведение реализации в C89 всегда было усечением до нуля.

Так% является оператором остатка в C99, C ++, а также в Java, но не является оператором остатка во всех языках программирования. В Ruby и Python,% фактически является оператором по модулю (целочисленное деление выполняется в направлении минус бесконечность в этих языках). Haskhell и Scheme имеют два отдельных оператора:mod а такжеrem для Хаскелла иmodulo а такжеremainder для схемы.

 NateS29 мар. 2013 г., 17:06
Хаскелл, а? ;)
Решение Вопроса

а не «остатком» (в математике ответ действительно должен быть 9).

C называет его оператором%, а его результат - остаток. C ++ копирует это из C. Ни один язык не называет это оператором модуля. Это также объясняет, почему остаток отрицательный: оператор / усекается до 0, а(a / b) * b + (a % b) должен равнятьсяa.

редактироватьДэвид Родригес справедливо отмечает, что C ++делает определить класс шаблонаstd::modulus, который вызываетoperator%, На мой взгляд, этот класс плохо назван. Копаясь немного, он унаследован от STL, где он уже назван, как сейчас. Загрузка для STL гласит: «STL был разработан на SGI MIPSproTM C ++ 7.0, 7.1, 7.2 и 7.2.1.» И, насколько я могу судить, фактически не имея компилятора и аппаратного обеспечения, MIPSpro передает деление на процессор и Аппаратные средства MIPS усекаются до 0, что означаетstd::modulus всегда был неправильно назван.

 user74338214 февр. 2012 г., 23:20
@ChadLaGuardia Также хороший пример неправильно названной функции, возвращаемое значение которой не указано полностью. C и C ++ с тех пор решили эту проблему, добавив более надежныйremainder функция, но я не думаю, что VS2003 имеет его.
 user74338214 февр. 2012 г., 23:02
@ DavidRodríguez-dribeas Хорошая находка, я не могу ответить об истории, стоящей за этим, и почему она названа как есть.
 Chad La Guardia14 февр. 2012 г., 23:10
Я думаю, что источником путаницы, по крайней мере для меня, является то, что если вы используетеfmodНапример, вы не получите истинный модуль, как следует из названия. Кажется, что эти два слова взаимозаменяемы. Но вы правы, настоящий стандарт C ++ говорит остаток. Первоначальный источник, который я использовал, был MSDN, потому что я искал специально для VS2003.msdn.microsoft.com/en-us/library/ty2ax9z9(v=vs.71).aspx, Казалось бы, они неверны.
 David Rodríguez - dribeas14 февр. 2012 г., 22:56
+1 Я только что проверил стандарт C ++:двоичный оператор% возвращает остаток от деления первого выражения на второе+1 для самого оператора. Теперь другая проблема - имя функтора вfunctional который используетoperator% который называетсямодультак что хотя бы часть вопроса осталась открытой ...

что проблема возникает из-за неправильного понимания математики. Конгруэнция по модулюотношение эквивалентноститак что это только определяетклассы эквивалентности, Следовательно, этоне правильно сказать, чтов математике ответ действительно должен быть 9потому что это может быть и 19, 29, и так далее. И конечно это может быть -1 или -11. Существуют бесконечные элементы класса чисел n, которые являются n ≡ -1 mod (10).

http://en.wikipedia.org/wiki/Modular_arithmetic

http://en.wikipedia.org/wiki/Congruence_relation

Итак, правильный вопрос может быть таким: какой элемент класса чисел, которые являются ≡ -1 mod (10), будет результатом -1% 10 в C ++? И ответ:остаток деления -1 на 10. Никаких загадок.

PS Ваше определение модуля и Кнута эквивалентно ... :)

 Ambroz Bizjak14 февр. 2012 г., 23:59
Многие ожидают, что операция% вернет уникального представителя класса эквивалентности. Это не так, потому что он возвращает разных представителей для пар целых чисел, принадлежащих к одному и тому же классу эквивалентности (x и -x, x! = 0). Ваш аргумент, что -1% 10 может быть -1 или -11, будет иметь смысл только в том случае, если всегда используется одно и то же смещение от [0, m-1] (например, если -1% 10 = -11, то 9% 10 тоже должно быть быть -11, а не 9).
 supercat19 дек. 2013 г., 22:38
@AmbrozBizjak: Другими словами, с математической точки зрения, утверждение(x % b)==(y % b) должно быть истинным, когда и только когда x и y находятся в одном классе эквивалентности mod b. Язык может, например, определить% оператор должен принять округленное деление (в этом случае знак результата будет указывать, как дивиденд должен быть скорректирован для достижения точного кратного делителя), и удовлетворить это ожидание, но оператор, реализованный в C, этого не делает.
 ascanio14 февр. 2012 г., 23:42
Почему? «Пусть q будет целочисленным отношением a и n», то же самое, что и «Пусть q будет полом деленного на n». Остальная часть определения совершенно одинакова, учитывая, что вы переворачиваете n * q с другой стороны равного ...;)
 Chad La Guardia14 февр. 2012 г., 23:35
Эти определения не равны. Подключите -1% 10, и вы поймете, почему.
 Ambroz Bizjak15 февр. 2012 г., 01:34
Я не говорю, что нет ничего плохого в том, как% определяется в C / C ++. Я просто говорю, что ожидание последовательного возврата значений из [0, m-1] имеет математическую основу. Повторим еще раз: многие ожидают, что операция% вернет уникального представителя класса эквивалентности. (и многие ожидают, что он будет вести себя именно так, как он)

Ваш ответ на вопрос