Mod avec des nombres négatifs donne un résultat négatif en Java et en C

Disons que j’ai (-5) mod 8 .

Je l’ai essayé dans les deux langages Java et C, et ils m’ont donné un résultat -5 alors que j’en attendais 3 .

Pourquoi cela arrive-t-il? Un module peut-il être négatif? Et que dois-je changer pour obtenir le résultat correct?

Code Java

 public class Example { public static void main(Ssortingng[] args) { int x; x = -5%8; System.out.println(x); } } 

Code C

 int main(){ int x; x = -5%8; printf("%d", x); } 

LES SORTIES

Entrez la description de l'image ici

    L’opérateur % est traité comme un opérateur restant, le signe du résultat est donc le même que celui du dividende.

    Si vous voulez une fonction modulo, vous pouvez faire quelque chose comme ceci:

     int mod(int a, int b) { int ret = a % b; if (ret < 0) ret += b; return ret; } 

    Pourquoi cela arrive-t-il?

    C’est défini comme cela en C. % est le rest de l’opérateur. Selon 6.5.5 Opérateurs multiplicatifs , paragraphe 6 de la norme C :

    Lorsque les entiers sont divisés, le résultat de l’opérateur / est le quotient algébrique, toute partie décimale étant ignorée. Si le quotient a/b est représentable, l’expression (a/b)*b + a%b doit être égale à a ; sinon, le comportement de a/b et de a%b n’est pas défini.

    C’est également défini de cette façon en Java. Selon 15.17.3. Opérateur restant% de la spécification Java 8 :

    On dit que l’opérateur% binary donne le rest de ses opérandes à partir d’une division implicite; l’opérande de gauche est le dividende et l’opérande de droite est le diviseur.

    En C et C ++, l’opérateur restant accepte uniquement les opérandes intégraux, mais dans le langage de programmation Java, il accepte également les opérandes à virgule flottante.

    L’opération restante pour les opérandes qui sont des entiers après la promotion numérique binary (§5.6.2) produit une valeur de résultat telle que (a / b) * b + (a% b) est égal à a.

    Cette identité est valable même dans le cas particulier où le dividende est l’entier négatif de la plus grande magnitude possible pour son type et le diviseur est -1 (le rest est 0).

    Il découle de cette règle que le résultat de l’opération du rest ne peut être négatif que si le dividende est négatif et ne peut être positif que si le dividende est positif. De plus, la magnitude du résultat est toujours inférieure à celle du diviseur.

    Ainsi, le rest – le résultat de l’opérateur % – doit avoir le même signe que le dividende – la première valeur, avant l’opérateur % .

    Ce n’est pas que le nombre soit négatif ou positif. 5%8 renverraient 5 car c’est ainsi que l’opérateur mod fonctionne.

    Si vous voulez 3 ou -3 comme résultat, vous devez faire 8%5 ou -8%5 respectivement.

    Voici la documentation, voici ce qu’elle dit:

    divise un opérande en un autre et renvoie le rest sous forme de résultat.

    Donc, c’est toujours l’opérande de sapin divisé par seconde. Aussi, si vous voulez un résultat positif, alors vous pouvez faire:

     Math.abs(-8%5); 

    Vous devriez avoir regardé la question du débordement de stack Quelle est la différence entre «mod» et «rest»? .

    Pour que le mod soit positif –

    Code C –

     int main(){ int a, b; scanf("%d %d", &a, &b); int rem = a%b; if (rem<0) rem += b; printf("%d", rem); return 0; } 

    Le code Java serait similaire.

    En gros, l'approche consiste à prendre d'abord mod indépendamment du signe (pour que l'ampleur de la réponse soit inférieure à celle du diviseur), et si la réponse est négative, ajoutez-y le diviseur.