Оператор Modulo с отрицательными значениями

Почему такие операции:

std::cout << (-7 % 3) << std::endl;
std::cout << (7 % -3) << std::endl;

дают разные результаты?

-1
1

Ответ 1

Из ISO14882: 2011 (e) 5.6-4:

Двоичный/оператор дает частное, а двоичный оператор% дает остаток от деления первого выражения на второй. Если второй операнд/или% равен нулю, поведение undefined. Для интегральных операндов оператор/дает алгебраическое отношение с любой дробной частью, отброшенной; если фактор a/b является представимый в типе результата, (a/b) * b + a% b равен a.

Остальное - базовая математика:

(-7/3) => -2
-2 * 3 => -6
so a%b => -1

(7/-3) => -2
-2 * -3 => 6
so a%b => 1

Обратите внимание, что

Если оба операнда неотрицательны, то остаток неотрицателен; если не, знак остатка определяется реализацией.

от ISO14882: 2003 (e) больше не присутствует в ISO14882: 2011 (e)

Ответ 2

Знак в таких случаях (т.е. когда один или оба операнда отрицательны) определяется реализацией. Спектр говорит в §5.6/4 (С++ 03),

Двоичный/оператор дает частное, а бинарный оператор% дает остаток от деления первого выражения на второе. Если второй операнд/или% равен нулю, поведение undefined; в противном случае (a/b) * b + a% b равно a. Если оба операнда неотрицательны, то остаток неотрицателен; , если нет, знак остатка определяется реализацией.

Это все, что должен сказать язык, что касается С++ 03.

Ответ 3

a % b

в С++ по умолчанию:

(-7/3) => -2
-2 * 3 => -6
so a%b => -1

(7/-3) => -2
-2 * -3 => 6
so a%b => 1

в python:

-7 % 3 => 2
7 % -3 => -2

в С++ для python:

(b + (a%b)) % b