Я сомневаюсь, что оператор остатка был намеренно разработан, чтобы иметь ту семантику, которая, я согласен, не очень полезна.(Вы когда-нибудь написали бы программу календаря, которая показывает будние дни воскресенье, анти-суббота, анти-пятница, ..., анти-понедельник для дат до эпохи?)
Скорее, отрицательные остатки являются побочным эффектомспособа целочисленного деления определяется.
A rem B := A - (A div B) * B
Если A div B
определено как trunc(A/B)
, вы получите оператор C's %
.Если A div B
определено как floor(A/B)
, вы получите оператор %
Python.Возможны и другие определения.
Итак, реальный вопрос заключается в следующем:
Почему в C ++, Java, C # и т. Д. Используется усеченное целочисленное деление?
Потому что такC делает это.
Почему C использует усеченное деление?
Изначально C не определял, как /
должен обрабатывать отрицательные числа.Он оставил это на усмотрение аппаратного обеспечения.
На практике в каждой существенной реализации C использовалось усеченное деление, поэтому в 1999 г. эта семантика была формально включена в стандарт C.
Почему аппаратное обеспечение используетсяусеченное деление?
Потому что это проще (= дешевле) реализовать с точки зрения беззнакового деления.Вы просто вычисляете abs(A) div abs(B)
и переворачиваете знак, если (A < 0) xor (B < 0)
.
Поэтажное деление имеет дополнительный шаг вычитания 1 из частного, если остаток ненулевой.