web-dev-qa-db-fra.com

Comment puis-je vérifier si un entier est pair ou impair?

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

193
chustar

Utilisez l'opérateur modulo (%) pour vérifier s'il y a un reste lors de la division par 2:

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

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

Par curiosité, j'ai créé deux programmes de test élémentaires 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:

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

J'ai examiné la sortie Assembly de chaque compilation (à l'aide de gcc -S) et constaté que, dans chaque cas, les sorties pour and.c et modulo.c étaient identiques (elles utilisaient toutes deux l'instruction andl $ 1,% eax). Je doute que ce soit une "nouvelle" fonctionnalité, et je soupçonne que cela remonte à des versions anciennes. Je doute également que tout compilateur non commercial, commercial ou open source moderne (fabriqué au cours des 20 dernières années) manque d'une telle optimisation. Je testerais sur d'autres compilateurs, mais je n'en ai pas pour le moment.

Si quelqu'un d'autre souhaitait tester d'autres compilateurs et/ou cibles de plate-forme et obtenir un résultat différent, je serais très intéressé de le savoir.

Enfin, la version modulo est garantie selon la norme, que l’entier soit positif, négatif ou nul, quelle que soit la représentation des entiers signés par l’implémentation. Le bitwise et la version n'est pas. Oui, je me rends compte que le complément de deux est un peu omniprésent, donc ce n'est pas vraiment un problème.

449
Chris Young

Vous êtes waaaaaaaaay trop efficace. 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 l'opération pour isEven.

Bien sûr, cela ne fonctionne pas pour les nombres négatifs. Mais avec la brillance vient le sacrifice ...

208
SCdF

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 module.

97
Adam Pierce

[Mode blague = "sur"]

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;
  }
}

[Mode blague = "off"]

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

36
Sklivvz

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 no , travaillez pas avec des nombres négatifs.

La norme C stipule que les nombres négatifs peuvent être représentés de 3 manières:

  • Complément de 2
  • Complément de 1
  • signe et grandeur

Vérifier comme ça:

isEven = (x & 1);

travaillera 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 pour m'avoir signalé que la zone de texte mangeait tout après mon personnage moins que fictif!

16
Andrew Edgecombe

Un gentil est:

/*forward declaration, C compiles in one pass*/
bool isOdd(unsigned int n);

bool isEven(unsigned int n)
{
  if (n == 0) 
    return true ;  // I know 0 is even
  else
    return isOdd(n-1) ; // n is even if n-1 is odd
}

bool isOdd(unsigned int n)
{
  if (n == 0)
    return false ;
  else
    return isEven(n-1) ; // n is odd if n-1 is even
}

Notez que cette méthode utilise la récursion de queue impliquant deux fonctions. Il peut être implémenté efficacement (transformé en une sorte de boucle while/Until) si votre compilateur supporte la récursion finale comme un compilateur Scheme. Dans ce cas, la pile ne doit pas déborder!

14
Pierre

Un nombre est pair si, lorsqu'il est divisé par deux, le reste est égal à 0. Un nombre est impair si, lorsqu'il est divisé par 2, le reste est égal à 1.

// Java
public static boolean isOdd(int num){
    return num % 2 != 0;
}

/* C */
int isOdd(int num){
    return num % 2;
}

Les méthodes sont géniales!

11
jjnguy
i % 2 == 0
8
Mark Cidade

Je dirais simplement diviser par 2 et s'il y a un reste 0, c'est pair, sinon c'est bizarre.

Utiliser le module (%) facilite cela.

par exemple. 4% 2 = 0 donc 4 est pair 5% 2 = 1 donc 5 est impair

7
Jarod Elliott

Je construirais un tableau des parités (0 si même 1 si impair) des nombres entiers (donc on pourrait faire une recherche: D), mais gcc ne me laissera pas faire des tableaux de telles tailles:

typedef unsigned int uint;

char parity_uint [UINT_MAX];
char parity_sint_shifted [((uint) INT_MAX) + ((uint) abs (INT_MIN))];
char* parity_sint = parity_sint_shifted - INT_MIN;

void build_parity_tables () {
    char parity = 0;
    unsigned int ui;
    for (ui = 1; ui <= UINT_MAX; ++ui) {
        parity_uint [ui - 1] = parity;
        parity = !parity;
    }
    parity = 0;
    int si;
    for (si = 1; si <= INT_MAX; ++si) {
        parity_sint [si - 1] = parity;
        parity = !parity;
    }
    parity = 1;
    for (si = -1; si >= INT_MIN; --si) {
        parity_sint [si] = parity;
        parity = !parity;
    }
}

char uparity (unsigned int n) {
    if (n == 0) {
        return 0;
    }
    return parity_uint [n - 1];
}

char sparity (int n) {
    if (n == 0) {
        return 0;
    }
    if (n < 0) {
        ++n;
    }
    return parity_sint [n - 1];
}

Donc, utilisons plutôt la définition mathématique de pair et impair.

Un entier n est même s'il existe un entier k tel que n = 2k.

Un entier n est impair s'il existe un entier k tel que n = 2k + 1.

Voici le code pour cela:

char even (int n) {
    int k;
    for (k = INT_MIN; k <= INT_MAX; ++k) {
        if (n == 2 * k) {
            return 1;
        }
    }
    return 0;
}

char odd (int n) {
    int k;
    for (k = INT_MIN; k <= INT_MAX; ++k) {
        if (n == 2 * k + 1) {
            return 1;
        }
    }
    return 0;
}

Soit C-integers les valeurs possibles de int dans une compilation C donnée. (Notez que C-integers est un sous-ensemble des entiers.)

Maintenant, on peut craindre que pour un n donné en C-nombres entiers, le nombre entier k correspondant puisse ne pas exister dans C-nombres entiers. Mais avec un peu de preuve, on peut montrer que pour tous les entiers n, | n | <= | 2n | (*), où | n | est "n si n est positif et -n sinon". En d'autres termes, pour tout n en entier, au moins un des blocages suivants (exactement les cas (1 et 2) ou les cas (3 et 4) en fait, mais je ne vais pas le prouver ici):

Cas 1: n <= 2n.

Cas 2: -n <= -2n.

Cas 3: -n <= 2n.

Cas 4: n <= -2n.

Maintenant, prenez 2k = n. (Un tel ak existe si n est pair, mais je ne le prouverai pas ici. Si n n'est pas pair, alors la boucle dans even ne rentre pas tôt de toute façon, donc cela n'a pas d'importance.) Mais cela implique k <n si n n'est pas 0 de (*) et le fait (encore non prouvé ici) que pour tout m, z en nombres entiers 2m = z implique que z n'est pas égal à m étant donné que m n'est pas 0. Dans le cas où n est 0, 2 * 0 = 0 donc 0 est même nous sommes faits (si n = 0 alors 0 est dans C-entiers car n est dans C-entier dans la fonction even, donc k = 0 est dans C-entiers) . Ainsi, un tel k dans C-integers existe pour n dans C-integer si n est pair.

Un argument similaire montre que si n est impair, il existe un k dans C-entiers tel que n = 2k + 1.

Par conséquent, les fonctions even et odd présentées ici fonctionneront correctement pour tous les entiers C.

6
Thomas Eding

Une autre solution au problème
(les enfants sont invités à voter)

bool isEven(unsigned int x)
{
  unsigned int half1 = 0, half2 = 0;
  while (x)
  {
     if (x) { half1++; x--; }
     if (x) { half2++; x--; }

  }
  return half1 == half2;
}
6
eugensk00
// C#
bool isEven = ((i % 2) == 0);
5
Michael Petrotta

Ceci fait suite à la discussion avec @RocketRoy concernant sa réponse , mais il pourrait être utile à quiconque souhaitant comparer ces résultats.

tl; dr D'après ce que j'ai vu, l'approche de Roy ((0xFFFFFFFF == (x | 0xFFFFFFFE)) n'est pas complètement optimisée pour x & 1 comme le mod approche, mais dans la pratique, les temps d'exécution devraient être égaux dans tous les cas.

Donc, d’abord, j’ai comparé la sortie compilée avec Compiler Explorer :

Fonctions testées:

int isOdd_mod(unsigned x) {
    return (x % 2);
}

int isOdd_and(unsigned x) {
    return (x & 1);
}

int isOdd_or(unsigned x) {
    return (0xFFFFFFFF == (x | 0xFFFFFFFE));
}   

Groupe 3.9.0 avec -O3:

isOdd_mod(unsigned int):                          # @isOdd_mod(unsigned int)
        and     edi, 1
        mov     eax, edi
        ret

isOdd_and(unsigned int):                          # @isOdd_and(unsigned int)
        and     edi, 1
        mov     eax, edi
        ret

isOdd_or(unsigned int):                           # @isOdd_or(unsigned int)
        and     edi, 1
        mov     eax, edi
        ret

GCC 6.2 avec -O3:

isOdd_mod(unsigned int):
        mov     eax, edi
        and     eax, 1
        ret

isOdd_and(unsigned int):
        mov     eax, edi
        and     eax, 1
        ret

isOdd_or(unsigned int):
        or      edi, -2
        xor     eax, eax
        cmp     edi, -1
        sete    al
        ret

Chapeau bas pour Clang, il s'est rendu compte que les trois cas sont fonctionnellement égaux. Cependant, l'approche de Roy n'est pas optimisée dans GCC, donc YMMV.

C'est similaire avec Visual Studio; inspectant la version x64 (VS2015) de désassemblage pour ces trois fonctions, j'ai pu voir que la partie de comparaison est égale pour les cas "mod" et "et", et légèrement plus grande pour le cas de Roy "ou":

// x % 2
test bl,1  
je (some address) 

// x & 1
test bl,1  
je (some address) 

// Roy's bitwise or
mov eax,ebx  
or eax,0FFFFFFFEh  
cmp eax,0FFFFFFFFh  
jne (some address)

Cependant, après l'exécution d'un test d'évaluation comparant ces trois options (modulaire, bit à bit ou, bit à bit et), les résultats étaient complètement égaux (encore une fois, Visual Studio 2005 x86/x64, version finale, aucun débogueur attaché).

Release Assembly utilise l'instruction test pour les cas and et mod, tandis que le cas de Roy utilise l'approche cmp eax,0FFFFFFFFh, mais elle est fortement déroulée et optimisée, de sorte qu'il n'y a aucune différence dans la pratique.

Mes résultats après 20 analyses (i7 3610QM, mode de gestion de l'alimentation de Windows 10 défini sur Haute performance):

 [Test: Plain mod 2] TEMPS MOYEN: 689.29 ms (Diff. Relative: +0.000%) 
 [Test: Bitwise ou] TEMPS MOYEN: 689.63 ms (Diff. Relative: + 0.048% ) 
 [Test: bits et] TEMPS MOYEN: 687.80 ms (Diff. Relative: -0.217%) 

La différence entre ces options étant inférieure à 0,3%, il est donc assez évident que l'Assemblée est égale dans tous les cas.

Voici le code si quelqu'un veut essayer, avec une mise en garde que je ne l'ai testé que sous Windows (vérifiez la condition #if LINUX pour la définition get_time et implémentez-la si nécessaire, à partir de this réponse ).

#include <stdio.h>

#if LINUX
#include <sys/time.h>
#include <sys/resource.h>
double get_time()
{
    struct timeval t;
    struct timezone tzp;
    gettimeofday(&t, &tzp);
    return t.tv_sec + t.tv_usec*1e-6;
}
#else
#include <windows.h>
double get_time()
{
    LARGE_INTEGER t, f;
    QueryPerformanceCounter(&t);
    QueryPerformanceFrequency(&f);
    return (double)t.QuadPart / (double)f.QuadPart * 1000.0;
}
#endif

#define NUM_ITERATIONS (1000 * 1000 * 1000)

// using a macro to avoid function call overhead
#define Benchmark(accumulator, name, operation) { \
    double startTime = get_time(); \
    double dummySum = 0.0, elapsed; \
    int x; \
    for (x = 0; x < NUM_ITERATIONS; x++) { \
        if (operation) dummySum += x; \
    } \
    elapsed = get_time() - startTime; \
    accumulator += elapsed; \
    if (dummySum > 2000) \
        printf("[Test: %-12s] %0.2f ms\r\n", name, elapsed); \
}

void DumpAverage(char *test, double totalTime, double reference)
{
    printf("[Test: %-12s] AVERAGE TIME: %0.2f ms (Relative diff.: %+6.3f%%)\r\n",
        test, totalTime, (totalTime - reference) / reference * 100.0);
}

int main(void)
{
    int repeats = 20;
    double runningTimes[3] = { 0 };
    int k;

    for (k = 0; k < repeats; k++) {
        printf("Run %d of %d...\r\n", k + 1, repeats);
        Benchmark(runningTimes[0], "Plain mod 2", (x % 2));
        Benchmark(runningTimes[1], "Bitwise or", (0xFFFFFFFF == (x | 0xFFFFFFFE)));
        Benchmark(runningTimes[2], "Bitwise and", (x & 1));
    }

    {
        double reference = runningTimes[0] / repeats;
        printf("\r\n");
        DumpAverage("Plain mod 2", runningTimes[0] / repeats, reference);
        DumpAverage("Bitwise or", runningTimes[1] / repeats, reference);
        DumpAverage("Bitwise and", runningTimes[2] / repeats, reference);
    }

    getchar();

    return 0;
}
4
Lou

En lisant cette discussion plutôt amusante, je me suis rappelé que j'avais une fonction sensible au temps qui vérifiait la présence de nombres pairs et impairs dans la boucle principale. Voici une fonction de puissance entière, publiée ailleurs sur StackOverflow, comme suit. Les repères étaient assez surprenants. Au moins dans cette fonction du monde réel, modulo est plus lent, et significativement. Le gagnant, avec une large marge, nécessitant 67% du temps de modulo, est une approche ou (|), et est introuvable ailleurs sur cette page.

static dbl  IntPow(dbl st0, int x)  {
    UINT OrMask = UINT_MAX -1;
    dbl  st1=1.0;
    if(0==x) return (dbl)1.0;

    while(1 != x)   {
        if (UINT_MAX == (x|OrMask)) {     //  if LSB is 1...    
        //if(x & 1) {
        //if(x % 2) {
            st1 *= st0;
        }    
        x = x >> 1;  // shift x right 1 bit...  
        st0 *= st0;
    }
    return st1 * st0;
}

Pour 300 millions de boucles, les timings de référence sont les suivants.

3.962 la | et approche du masque

4.851 l'approche &

5.850 l'approche%

Pour les personnes qui pensent que la théorie, ou une liste de langue d'assemblée, règle des arguments comme ceux-ci, ceci devrait être un récit édifiant. Il y a plus de choses dans le ciel et la terre, Horatio, que ce que votre philosophie vous fait rêver.

4
user1899861

Essayez ceci: return (((a>>1)<<1) == a)

Exemple:

a     =  10101011
-----------------
a>>1 --> 01010101
a<<1 --> 10101010

b     =  10011100
-----------------
b>>1 --> 01001110
b<<1 --> 10011100
4
Kiril Aleksandrov

Voici une réponse en Java:

public static boolean isEven (Integer Number) {
    Pattern number = Pattern.compile("^.*?(?:[02]|8|(?:6|4))$");
    String num = Number.toString(Number);
    Boolean numbr = new Boolean(number.matcher(num).matches());
    return numbr.booleanValue();
}
4
Thomas Eding

Dans la "catégorie créative mais déroutante", je propose:

int isOdd(int n) { return n ^ n * n ? isOdd(n * n) : n; }

Une variante de ce thème spécifique à Microsoft C++:

__declspec(naked) bool __fastcall isOdd(const int x)
{
    __asm
    {
        mov eax,ecx
        mul eax
        mul eax
        mul eax
        mul eax
        mul eax
        mul eax
        ret
    }
}
3
DocMax

Je sais que c'est juste du sucre syntaxique et niquement applicable en .net mais qu'en est-il de la méthode d'extension ...

public static class RudiGroblerExtensions
{
    public static bool IsOdd(this int i)
    {
        return ((i % 2) != 0);
    }
}

Maintenant, vous pouvez faire ce qui suit

int i = 5;
if (i.IsOdd())
{
    // Do something...
}
3
rudigrobler

La méthode au niveau du bit dépend de la représentation interne de l'entier. Modulo fonctionnera partout où il y a un opérateur modulo. Par exemple, certains systèmes utilisent réellement les bits de bas niveau pour le balisage (comme les langages dynamiques), de sorte que les données brutes x & 1 ne fonctionnent pas dans ce cas.

2
Will Hartung

IsOdd (int x) {retourne vrai; }

Preuve d'exactitude - considérons l'ensemble de tous les entiers positifs et supposons qu'il existe un ensemble d'entiers non vides qui ne sont pas impairs. Parce que les entiers positifs sont bien ordonnés, il y aura un plus petit nombre non impair, ce qui en soi est assez étrange, donc clairement ce nombre ne peut pas être dans l'ensemble. Par conséquent, cet ensemble ne peut pas être non vide. Répétez l'opération pour les nombres entiers négatifs, sauf chercher le plus grand nombre non impair.

2
plinth

Comme certaines personnes l'ont signalé, il existe de nombreuses façons de le faire. Selon ce site , le moyen le plus rapide est l'opérateur de module:

if (x % 2 == 0)
               total += 1; //even number
        else
               total -= 1; //odd number

Cependant, voici quelques autre code qui a été marqué au banc par l'auteur qui a fonctionné plus lentement que l'opération de module commun ci-dessus:

if ((x & 1) == 0)
               total += 1; //even number
        else
               total -= 1; //odd number

System.Math.DivRem((long)x, (long)2, out outvalue);
        if ( outvalue == 0)
               total += 1; //even number
        else
               total -= 1; //odd number

if (((x / 2) * 2) == x)
               total += 1; //even number
        else
               total -= 1; //odd number

if (((x >> 1) << 1) == x)
               total += 1; //even number
        else
               total -= 1; //odd number

        while (index > 1)
               index -= 2;
        if (index == 0)
               total += 1; //even number
        else
               total -= 1; //odd number

tempstr = x.ToString();
        index = tempstr.Length - 1;
        //this assumes base 10
        if (tempstr[index] == '0' || tempstr[index] == '2' || tempstr[index] == '4' || tempstr[index] == '6' || tempstr[index] == '8')
               total += 1; //even number
        else
               total -= 1; //odd number

Combien de personnes connaissaient même la méthode Math.System.DivRem ou pourquoi l'utilisaient-elles ??

2
user3810900

Portable:

i % 2 ? odd : even;

Unportable:

i & 1 ? odd : even;

i << (BITS_PER_INT - 1) ? odd : even;
2
ilitirit

Nombre zéro parité | zéro http://tinyurl.com/oexhr3k

Séquence de code Python.

# defining function for number parity check
def parity(number):
    """Parity check function"""
    # if number is 0 (zero) return 'Zero neither ODD nor EVEN',
    # otherwise number&1, checking last bit, if 0, then EVEN, 
    # if 1, then ODD.
    return (number == 0 and 'Zero neither ODD nor EVEN') \
            or (number&1 and 'ODD' or 'EVEN')

# cycle trough numbers from 0 to 13 
for number in range(0, 14):
    print "{0:>4} : {0:08b} : {1:}".format(number, parity(number))

Sortie:

   0 : 00000000 : Zero neither ODD nor EVEN
   1 : 00000001 : ODD
   2 : 00000010 : EVEN
   3 : 00000011 : ODD
   4 : 00000100 : EVEN
   5 : 00000101 : ODD
   6 : 00000110 : EVEN
   7 : 00000111 : ODD
   8 : 00001000 : EVEN
   9 : 00001001 : ODD
  10 : 00001010 : EVEN
  11 : 00001011 : ODD
  12 : 00001100 : EVEN
  13 : 00001101 : ODD
1
user1630938
int isOdd(int i){
  return(i % 2);
}

terminé.

1
None

Pour donner plus de détails sur la méthode des opérateurs au niveau du bit pour ceux d’entre nous qui n’avons pas fait l’algèbre booléenne au cours de nos études, voici une explication. Probablement pas d'une grande utilité pour l'OP, mais j'avais envie d'expliquer clairement pourquoi NUMBER & 1 fonctionnait.

Veuillez noter que, comme le répète une personne ci-dessus, la façon dont les nombres négatifs sont représentés peut empêcher cette méthode de fonctionner. En fait, cela peut même briser la méthode d'opérateur modulo puisque chaque langue peut différer dans la façon dont elle traite les opérandes négatifs.

Cependant, si vous savez que NUMBER sera toujours positif, cela fonctionnera bien.

Comme Tooony ci-dessus a souligné le fait que seul le dernier chiffre en binaire (et denary) est important.

Une porte logique ET booléenne indique que les deux entrées doivent être un 1 (ou une tension élevée) pour que 1 soit renvoyée.

1 & 0 = 0.

0 & 1 = 0.

0 & 0 = 0.

1 & 1 = 1.

Si vous représentez n'importe quel nombre sous forme binaire (j'ai utilisé une représentation de 8 bits ici), les nombres impairs ont 1 à la fin, les nombres pairs ont 0.

Par exemple:

1 = 00000001

2 = 00000010

3 = 00000011

4 = 00000100

Si vous prenez un nombre et que vous utilisez AND (& en Java) au nombre de bits par 1, il renvoie soit 00000001, = 1, ce qui signifie que le nombre est impair. Ou 00000000 = 0, ce qui signifie que le nombre est pair.

Par exemple

Est impair?

1 & 1 =

00000001 et

00000001 =

00000001 <- Impair

2 & 1 =

00000010 &

00000001 =

00000000 <- Pair

54 & 1 =

00000001 et

00110110 =

00000000 <- Pair

C'est pourquoi cela fonctionne:

if(number & 1){

   //Number is odd

} else {

   //Number is even
}

Désolé si c'est redondant.

1
Astridax
I execute this code for ODD & EVEN:

#include <stdio.h>
int main()
{
    int number;
    printf("Enter an integer: ");
    scanf("%d", &number);

    if(number % 2 == 0)
        printf("%d is even.", number);
    else
        printf("%d is odd.", number);
}
1
Omar Faruk

Vérifier même ou impair est une tâche simple.

Nous savons que tout nombre exactement divisible par 2 est un nombre pair, sinon impair.

Nous avons juste besoin de vérifier la divisibilité d'un nombre quelconque et pour vérifier la divisibilité, nous utilisons l'opérateur %.

Vérification même impaire en utilisant if else

if(num%2 ==0)  
{
    printf("Even");
}
else
{
    printf("Odd");
}

programme C pour vérifier même ou impair en utilisant if else

Utilisation de l'opérateur conditionnel/ternaire

(num%2 ==0) printf("Even") : printf("Odd");

programme C pour vérifier même ou impair en utilisant un opérateur conditionnel .

Utilisation de l'opérateur Bitwise

if(num & 1)  
{
    printf("Odd");
}
else 
{
    printf("Even");
}
0
Pankaj Prakash

+ 66% plus rapide> !(i%2) / i%2 == 0

int isOdd(int n)
{
    return n & 1;
}

Le code vérifie le dernier bit de l’entier s’il s’agit de 1 en binaire

Explication

Binary  :   Decimal
-------------------
0000    =   0
0001    =   1
0010    =   2
0011    =   3
0100    =   4
0101    =   5
0110    =   6
0111    =   7
1000    =   8
1001    =   9
and so on...

Avis le plus à droite bit est toujours 1 pour Impair nombres.

l'opérateur & bit AND vérifie le bit le plus à droite de notre ligne retour si c'est 1

Pensez-y comme vrai et faux

Lorsque nous comparons n à 1, ce qui signifie 0001 en binaire (le nombre de zéros n'a pas d'importance).
alors imaginons que nous avons l'entier n avec une taille de 1 octet.

Il serait représenté par des chiffres de 8 bits/8-binaires.

Si l'int n était 7 et que nous le comparons avec 1, c'est comme

7 (1-byte int)|    0  0  0  0    0  1  1  1
       &
1 (1-byte int)|    0  0  0  0    0  0  0  1
********************************************
Result        |    F  F  F  F    F  F  F  T

Qui F signifie faux et T pour vrai.

Il compare seulement le bit le plus à droite s’ils sont tous les deux vrais. Donc, automagiquement 7 & 1 est T rue.

Et si je veux vérifier le bit avant le plus à droite?

Remplacez simplement n & 1 par n & 2 dont 2 représente 0010 en binaire et ainsi de suite.

Je suggère d'utiliser la notation hexadécimale si vous êtes débutant aux opérations au niveau des bits
return n & 1; >> return n & 0x01;.

0
X Stylish

Par souci de discussion ...

Il suffit de regarder le dernier chiffre d'un chiffre pour voir s'il est pair ou impair. Signé, non signé, positif, négatif - ils sont tous les mêmes à cet égard. Donc, cela devrait fonctionner tout autour: -

void tellMeIfItIsAnOddNumberPlease(int iToTest){
  int iLastDigit;
  iLastDigit = iToTest - (iToTest / 10 * 10);
  if (iLastDigit % 2 == 0){
    printf("The number %d is even!\n", iToTest);
  } else {
    printf("The number %d is odd!\n", iToTest);
  }
}

La clé ici est dans la troisième ligne de code, l'opérateur de division effectue une division entière, de sorte qu'il manque la partie fraction du résultat dans le résultat. Ainsi, par exemple, 222/10 donnera 22 comme résultat. Puis multipliez-le à nouveau par 10 et vous avez 220. Soustrayez cela de l'original 222 et vous vous retrouvez avec 2, qui correspond par magie au même nombre que le dernier chiffre du nombre d'origine. ;-) Les parenthèses sont là pour nous rappeler l’ordre dans lequel le calcul est effectué. Commencez par diviser et multiplier, puis soustrayez le résultat du nombre initial. Nous pourrions les laisser de côté, car la priorité est plus élevée pour la division et la multiplication que pour la soustraction, mais cela nous donne un code "plus lisible".

Nous pourrions rendre le tout complètement illisible si nous le voulions. Cela ne ferait aucune différence pour un compilateur moderne: -

printf("%d%s\n",iToTest,0==(iToTest-iToTest/10*10)%2?" is even":" is odd");

Mais cela rendrait le code beaucoup plus difficile à maintenir dans le futur. Imaginez simplement que vous souhaitiez changer le texte des nombres impairs en "n’est pas pair". Ensuite, quelqu'un d'autre voudra plus tard savoir quelles modifications vous avez apportées et effectuer un diff svn ou similaire ...

Si vous n'êtes pas inquiet à propos de la portabilité, mais plutôt de la vitesse, vous pouvez jeter un coup d'œil au bit le moins important. Si ce bit est défini sur 1, il s'agit d'un nombre impair, s'il est égal à 0, il s'agit d'un nombre pair. Sur un petit système endian, comme l'architecture x86 d'Intel, cela ressemblerait à ceci: -

if (iToTest & 1) {
  // Even
} else {
  // Odd
}
0
Tooony

Si vous voulez être efficace, utilisez les opérateurs au niveau des bits (x & 1), mais si vous voulez être lisible, utilisez modulo 2 (x % 2)

0
Vihung