262 votes

Opération modulo avec des nombres négatifs

Dans un programme C, j'ai essayé les opérations suivantes (juste pour vérifier le comportement)

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

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

Cela m'a donné le résultat suivant (2, -2 , -2) dans gcc. Je m'attendais à un résultat positif à chaque fois. Un modulus peut-il être négatif ? Quelqu'un peut-il expliquer ce comportement ?

220voto

ArjunShankar Points 8476

C99 nécessite que lorsque a/b est représentable :

(a/b) * b + a%b est égal à a

Cela a du sens, logiquement. N'est-ce pas ?

Voyons ce que cela donne :


Exemple A. 5/(-3) es -1

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

Cela ne peut se produire que si 5%(-3) est de 2.


Exemple B. (-5)/3 es -1

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

Cela ne peut se produire que si (-5)%3 es -2

208voto

ouah Points 75311

El % en C n'est pas l'opérateur modulo mais l'opérateur reste opérateur.

Les opérateurs modulo et reste diffèrent en ce qui concerne les valeurs négatives.

Avec un opérateur de reste, le signe du résultat est le même que celui du dividende (numérateur) alors qu'avec un opérateur modulo, le signe du résultat est le même que celui du diviseur (dénominateur).

C définit le % opération pour a % b comme :

  a == (a / b * b) + a % b

avec / la division entière avec troncature vers 0 . C'est la troncature qui est faite vers 0 (et non vers l'inifinité négative) qui définit la % comme un opérateur de reste plutôt qu'un opérateur modulo.

89voto

dewang Points 111

Basé sur la spécification C99 : a == (a / b) * b + a % b

Nous pouvons écrire une fonction pour calculer (a % b) == a - (a / b) * b ¡!

int remainder(int a, int b)
{
    return a - (a / b) * b;
}

Pour l'opération modulo, nous pouvons avoir la fonction suivante (en supposant que b > 0 )

int mod(int a, int b)
{
    int r = a % b;
    return r < 0 ? r + b : r;
}

Ma conclusion est que a % b en C est une opération de reste et NON une opération modulo.

79voto

Udayraj Deshmukh Points 853

Je pense qu'il n'y a pas besoin de vérifier si le nombre est négatif.

Une fonction simple pour trouver le modulo positif serait celle-ci -

Edit : En supposant que N > 0 y N + N - 1 <= INT_MAX

int modulo(int x,int N){
    return (x % N + N) %N;
}

Cela fonctionnera pour à la fois positif et négatif valeurs de x.

Original P.S : Comme l'a également souligné @chux, si vos x et N peuvent atteindre quelque chose comme INT_MAX-1 et INT_MAX respectivement, il suffit de remplacer int con long long int .

Et s'ils franchissent également les limites de la grande longueur (c'est-à-dire près de LLONG_MAX), alors vous devez traiter les cas positifs et négatifs séparément comme décrit dans d'autres réponses ici.

10voto

Yu Hao Points 40603

Les autres réponses ont expliqué dans C99 ou plus, la division d'entiers impliquant des opérandes négatifs est toujours tronquer vers zéro .

Notez que, dans C89 Le fait que le résultat soit arrondi à la hausse ou à la baisse dépend de la mise en œuvre. Parce que (a/b) * b + a%b est égal à a dans toutes les normes, le résultat de % impliquant des opérandes négatifs est également définie par l'implémentation en C89.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X