Операция по модулю с отрицательными числами


196

В программе на Си я пробовал следующие операции (просто чтобы проверить поведение)

 x = 5 % (-3);
 y = (-5) % (3);
 z = (-5) % (-3); 

printf("%d ,%d ,%d", x, y, z); 

дал мне вывод как (2, -2 , -2)в gcc. Я ожидал положительного результата каждый раз. Может ли модуль быть отрицательным? Кто-нибудь может объяснить это поведение?


Возможный дубликат stackoverflow.com/questions/4003232/…
Джеймс

Ответы:


170

C99 требует, чтобы, когда a/bпредставимо:

(a/b) * b + a%b должен равнятьсяa

Это логично, логично. Правильно?

Посмотрим, к чему это приведет:


Пример А. 5/(-3)является-1

=> (-1) * (-3) + 5%(-3) =5

Это может произойти, только если 5%(-3)2.


Пример Б. (-5)/3является-1

=> (-1) * 3 + (-5)%3 =-5

Это может произойти только тогда , когда (-5)%3это-2


1
Должен ли компилятор быть достаточно умным и обнаруживать, что неподписанный по модулю другой неподписанный всегда положителен? В настоящее время (ну, GCC 5.2) компилятор, кажется, думает, что «%» возвращает «int» в этом случае, а не «unsigned», даже если оба операнда имеют значение uint32_t или больше.
Фредерик Норд

@FrederickNord У вас есть пример, чтобы показать такое поведение ?
chux - Восстановить Монику

11
Поймите, что вы описываете обычное int (a / b) (усеченное) описание мода. Но также возможно, что это правило пола (а / б) (Кнут). В случае Кнута -5/3есть -2и мод становится 1. Короче: один модуль имеет знак, который следует за знаком дивиденда (усеченный), другой модуль имеет знак, который следует за знаком делителя (Кнут).
Исаак

1
Это тот случай, когда стандарт Си не совсем то, что я хочу. Я никогда не хотел урезать до нуля или отрицательных чисел по модулю, но часто хочу обратное и нужно работать вокруг C.
Джо
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.