4 votes

le modulus renvoie un montant incorrect dans le programme c lorsqu'un nombre négatif est entré

Quelqu'un peut-il m'aider à comprendre pourquoi ce programme donne une réponse erronée pour une opération de modulus lorsqu'un nombre négatif est saisi dans ce programme C ?

Je suis presque sûr que ce qui cause les problèmes est le scanf fonction. La réponse correcte est donnée lorsque des nombres entiers positifs sont utilisés.

Le code est ci-dessous :

#include <stdio.h>

int main()
{
    int num1 = 0;
    int num2 = 0;
    int answer = 0;
    puts("enter two number to find the modulus of...");
    if (scanf("%3d %3d",&num1,&num2) != 2)
            puts("something went wrong");
    else {
            answer = (num1 % num2);
            printf("the modulus of %d and %d is: %d\n", num1, num2, answer);
    }
}

4voto

luser droog Points 9030

En ANSI C, le signe du résultat de l'opérateur de modulation n'est pas défini pour les entrées négatives. Vous pouvez essayer div() de la bibliothèque de mathématiques ( réf. ). Il renvoie une structure avec le quotient et le reste, et il fonctionne de manière fiable pour les entrées négatives.

Ou, comme Alexey Frunze le suggère gentiment, vous pouvez activer le mode C99. Je suis trop paresseux pour chercher la norme, mais un petit test ( gcc -std=c99 ) suggère que le signe du résultat correspond au signe de l'opérande de gauche. Donc div() est toujours le meilleur si vous voulez la compatibilité ANSI.

Ou, vous pouvez prendre le contrôle total de la situation. Mais vous devez choisir ce que correct moyens. Le texte suivant est tiré de Wikipedia .

int x, y, q, r; // all snippets: left-arg, right-arg, quotient, remainder

division tronquée

q = trunc( (double)x / y);
r = x - y * q;

division floored (Knuth)

q = floor( (double)x / y);
r = x - y * q;

division euclidienne

q = y > 0 ? floor( (double)x / y) : ceiling( (double)x / y);
r = x - y * q;

2voto

chux Points 13185

Après avoir accepté la réponse

En C, depuis C99, le résultat de % es bien défini même avec des opérandes négatifs. Voir ci-dessous.

En C, % L'opérateur est nommé "remainder" en C et non "modulus".

Pour effectuer une division et un reste euclidiens sans en subissant la troncature, la gamme, double problèmes de conversion ** :

void Euclidean_divide_remainder(int a, int b, int *q, int *r) {
  *q = a / b;
  *r = a % b;
  if (a < 0 && *r != 0) {
    if (b < 0) { (*q)++; *r -= b; }
    else {       (*q)--; *r += b; }
  }
}

void rtest(int a, int b) {
  int eq, er;
  Euclidean_divide_remainder(a, b, &eq, &er);
  printf("f(%2d,%2d) / %2d  %% %2d  E/ %2d  E%% %2d\n", 
      a, b, a / b, a % b, eq, er);
}

void rtest4(int a, int b) {
  rtest(a, b);
  rtest(a, -b);
  rtest(-a, b);
  rtest(-a, -b);
  printf("\n");
}

int main(void) {
  rtest4(7, 3);
  return 0;
}

f( 7, 3) /  2  %  1  E/  2  E%  1
f( 7,-3) / -2  %  1  E/ -2  E%  1
f(-7, 3) / -2  % -1  E/ -3  E%  2
f(-7,-3) /  2  % -1  E/  3  E%  2

Le résultat de l'opérateur / est le quotient de la division du premier opérande par le second ; le résultat de l'opérateur / est le quotient de la division du premier opérande par le second. le résultat de l'opérateur % est le reste . Dans ces deux opérations, si la valeur du second opérande est nulle, le comportement est indéfini. C11dr §6.5.5 5

Lorsque des entiers sont divisés, le résultat de l'opérateur / est le quotient algébrique avec n'importe quel partie fractionnaire éliminée. (Cette opération est souvent appelée ''troncature vers zéro''). a/b est représentable, l'expression (a/b)*b + a%b est égal à a ; sinon, le comportement des deux a/b y a%b est indéfini. C11dr §6.5.5 6

** Exceptions :

Le résultat de a%0 est indéfinie.

Pour le complément à 2, INT_MIN % -1 y INT_MIN E% -1 (qui mathématiquement devrait être 0) sont des problèmes. Ceci est causé par INT_MIN / -1 (qui mathématiquement devrait être INT_MAX + 1 ) pose un problème car la réponse ne rentre pas dans le cadre de l'article. int gamme..

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