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

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

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

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

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

Пусть q - целое число a и n. Пусть г - остаток. Тогда:

a = n * q + r

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

Пусть q - пол деления на n. Пусть г - остаток. Тогда:

r = a - n * q

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

Для справки:

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

4b9b3361

Ответ 1

Мне кажется неправильным назвать его "модулем", а не "остатком" (в математике ответ действительно должен быть 9).

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

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

Ответ 2

% - оператор остатка в C и С++.

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

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

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

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

В связи с тем, что C изменило реализацию, определенную поведением целочисленного деления относительно усечения, Дуг Гвин из C комитета сказал:

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

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

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

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

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

Ответ 3

Я боюсь, что проблема возникает из-за непонимания математики. Конгруэнция по модулю n является отношением эквивалентности, поэтому она определяет только классы эквивалентности. Следовательно, он не правильно сказал, что "в математике ответ действительно должен быть 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 в С++? И ответ таков: остаток от деления -1 на 10. Нет тайны.

PS Ваше определение модуля и Knuth равно ehm, равно...:)