193 votes

Comment vérifier si un nombre entier est pair ou impair ?

Comment puis-je vérifier si un nombre donné est pair ou impair en C ?

5 votes

La version qui utilise le bitwise et (&) est beaucoup plus efficace que la version modulo (%). Vous devriez changer celle que vous avez choisie comme réponse correcte.

6 votes

Peu probable que cela ait de l'importance - l'argument est une constante. Facile pour l'optimiseur

1 votes

Avez-vous fait un benchmark ? Les performances des différentes constructions dépendent fortement du compilateur, de votre CPU et d'autres effets secondaires.

449voto

Chris Young Points 8525

Utilisez l'opérateur modulo (%) pour vérifier s'il y a un reste lorsqu'on divise par 2 :

if (x % 2) { /* x is odd */ }

Quelques personnes ont critiqué ma réponse ci-dessus en déclarant que l'utilisation de x & 1 est "plus rapide" ou "plus efficace". Je ne pense pas que ce soit le cas.

Par curiosité, j'ai créé deux programmes de test triviaux :

/* modulo.c */
#include <stdio.h>

int main(void)
{
    int x;
    for (x = 0; x < 10; x++)
        if (x % 2)
            printf("%d is odd\n", x);
    return 0;
}

/* and.c */
#include <stdio.h>

int main(void)
{
    int x;
    for (x = 0; x < 10; x++)
        if (x & 1)
            printf("%d is odd\n", x);
    return 0;
}

Je les ai ensuite compilés avec gcc 4.1.3 sur l'une de mes machines 5 fois différentes :

  • Sans drapeaux d'optimisation.
  • Avec -O
  • Avec -Os
  • Avec -O2
  • Avec -O3

J'ai examiné la sortie de l'assemblage de chaque compilation (en utilisant gcc -S) et j'ai constaté que dans chaque cas, la sortie de and.c et de modulo.c était identique (ils utilisaient tous deux l'instruction andl $1, %eax). Je doute que ce soit une "nouvelle" fonctionnalité, et je soupçonne que cela remonte à d'anciennes versions. Je doute également qu'un compilateur moderne (fait au cours des 20 dernières années) non-arcane, commercial ou open source, manque d'une telle optimisation. Je testerais bien sur d'autres compilateurs, mais je n'en ai aucun de disponible pour le moment.

Si quelqu'un d'autre souhaite tester d'autres compilateurs et/ou d'autres plates-formes cibles et obtient un résultat différent, je serais très intéressé de le savoir.

Enfin, la version modulo est garanti par la norme pour travailler si l'entier est positif, négatif ou nul, quelle que soit la représentation des entiers signés de l'implémentation. La version bitwise-and ne l'est pas. Oui, je réalise que le complément à deux est quelque peu omniprésent, donc ce n'est pas vraiment un problème.

1 votes

Pour Java, cela doit être : if (x % 2 == 0) { /* x est impair */ } Les entiers n'étant pas automatiquement traités comme des booléens dans les instructions if.

11 votes

La question demandait spécifiquement comment le faire en C, j'ai donc répondu en C, bien que chustar ait mentionné qu'il ne pouvait pas trouver comment le faire en Java. Je n'ai pas prétendu ou laissé entendre que c'était une réponse en Java, je ne connais pas Java. Je pense que je viens de recevoir mon premier vote négatif et je ne sais pas pourquoi. Mais bon.

33 votes

Je dirais, si (x % 2 != 0) { /* x est impair */ }, mais qui sait. Je ne connais pas non plus la java.

207voto

SCdF Points 11397

Vous êtes beaucoup trop efficaces. Ce que vous voulez vraiment c'est :

public boolean isOdd(int num) {
  int i = 0;
  boolean odd = false;

  while (i != num) {
    odd = !odd;
    i = i + 1;
  }

  return odd;
}

Répétez pour isEven .

Bien sûr, ça ne marche pas pour les nombres négatifs. Mais avec l'intelligence vient le sacrifice...

0 votes

Je dois être d'accord... intéressant, mais un peu dément. Si c'était slashdot, vous auriez un upvote pour l'humour. Je ne peux pas recommander cette solution cependant :)

17 votes

Si vous lanciez une exception d'argument sur les valeurs négatives, et si vous indiquiez dans la documentation que cette fonction est O(N), alors je serais tout à fait d'accord avec cela.

0 votes

Voté pour m'avoir fait sourire.

97voto

Adam Pierce Points 12801

Utilisez l'arithmétique des bits :

if((x & 1) == 0)
    printf("EVEN!\n");
else
    printf("ODD!\n");

C'est plus rapide que d'utiliser la division ou le modulus.

0 votes

C'est exactement ce que je viens de poster. Un vote pour avoir un grand esprit ;)

43 votes

Je ne pense pas qu'il soit juste de dire que c'est plus rapide que d'utiliser la division ou le modulus. La norme C ne dit rien sur les performances des opérateurs, et tout compilateur décent produira un code rapide pour l'un ou l'autre. Personnellement, je choisirais l'idiome qui communique mon intention, et % semble plus approprié ici.

1 votes

Je suis d'accord avec Chris Young - je crois que n'importe quel compilateur C/C++ moderne réduira l'opération "% 2" à un test de bit. Au moins pour les constructions non déboguées.

36voto

Sklivvz Points 16412

[Joke mode="on"]

public enum Evenness
{
  Unknown = 0,
  Even = 1,
  Odd = 2
}

public static Evenness AnalyzeEvenness(object o)
{

  if (o == null)
    return Evenness.Unknown;

  string foo = o.ToString();

  if (String.IsNullOrEmpty(foo))
    return Evenness.Unknown;

  char bar = foo[foo.Length - 1];

  switch (bar)
  {
     case '0':
     case '2':
     case '4':
     case '6':
     case '8':
       return Evenness.Even;
     case '1':
     case '3':
     case '5':
     case '7':
     case '9':
       return Evenness.Odd;
     default:
       return Evenness.Unknown;
  }
}

[Joke mode="off"]

EDIT : Ajout de valeurs déroutantes à l'enum.

2 votes

Wow... c'est plus dément que la solution de SCdF ! Kudos ! Pas d'upvote cependant... je ne peux pas la recommander. Mais merci pour l'humour !

1 votes

L'avantage de cette approche est qu'elle fonctionne avec plus que des chiffres. En outre, si vous remplacez la ligne suivante : char bar = foo[foo.Length - 1] ; par la suivante : double bar = Char.GetNumericValue(foo[foo.Length - 1]) ; cela fonctionnera avec n'importe quel système numérique.

0 votes

M'a fait rire à gorge déployée.

16voto

Andrew Edgecombe Points 13183

En réponse à ffpf - J'ai eu exactement le même argument avec un collègue il y a des années, et la réponse est la suivante pas de il ne fonctionne pas avec les nombres négatifs.

La norme C stipule que les nombres négatifs peuvent être représentés de 3 façons :

  • Complément à 2
  • Complément à 1
  • le signe et la magnitude

En vérifiant comme ça :

isEven = (x & 1);

fonctionnera pour le complément à 2 et la représentation du signe et de la magnitude, mais pas pour le complément à 1.

Cependant, je pense que ce qui suit fonctionnera dans tous les cas :

isEven = (x & 1) ^ ((-1 & 1) | ((x < 0) ? 0 : 1)));

Merci à ffpf de m'avoir fait remarquer que la zone de texte mangeait tout ce qui se trouvait après mon caractère moins que !

0 votes

Je pense qu'il manque du texte dans votre deuxième exemple de code.

3 votes

Allons complimenter ces chiffres !

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