Question

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

Était-ce utile?

La solution

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 en déclarant que l'utilisation de x & amp; 1 est & Quot; plus rapide & Quot; 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 une de mes machines à 5 reprises:

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

J'ai examiné la sortie d'assemblage de chaque compilation (à l'aide de gcc -S) et constaté que, dans chaque cas, les résultats de sortie pour and.c et modulo.c étaient identiques (ils utilisaient tous les deux l'instruction andl $ 1,% eax). Je doute que ce soit un & "Nouveau &"; 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 est garantie par le standard de fonctionner si l'entier est positif, négatif ou égal à zéro, quelle que soit la représentation des entiers signés dans 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.

Autres conseils

Vous êtes trop efficaces, waaaaaaaaay. 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éter pour isEven.

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

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

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

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

Le standard 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 magnitude

En vérifiant comme ceci:

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 pour avoir signalé que la zone de texte mangeait tout après mon personnage inférieur à!

Un bon 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 une récursion avec deux fonctions. Il peut être implémenté efficacement (transformé en une sorte de boucle while / Until) si votre compilateur prend en charge la récursion finale comme un compilateur Scheme. Dans ce cas, la pile ne doit pas déborder!

Un nombre est pair si, divisé par deux, le reste est égal à 0. Un nombre est impair si, 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!

i % 2 == 0

Je dirais simplement de le diviser par 2 et s'il reste 0, c'est pair, sinon c'est étrange.

L’utilisation du module (%) facilite les choses.

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

Une solution de plus 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;
}

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

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

Alors, recourons 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.

En voici le code:

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 s'inquiéter du fait que pour un n donné en C-entiers, l'entier correspondant k pourrait ne pas exister dans C-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, la boucle dans even ne retourne pas de toute façon, donc cela n'a pas d'importance.) Mais cela implique que k < !> lt; n si n n'est pas 0 de (*) et le fait (encore une fois non prouvé ici) que pour tout m, z en nombres entiers 2m = z implique que z n'est pas égal à m étant donné m n'est pas 0. Dans le cas où n est 0, 2 * 0 = 0 donc 0 est même que nous avons terminé (si n = 0 alors 0 est dans C-entiers car n est dans C-entier dans la fonction odd, 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.

Les fonctions <=> et <=> présentées ici fonctionneront donc correctement pour tous les C-entiers.

// C#
bool isEven = ((i % 2) == 0);

Voici une réponse dans 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();
}

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

Exemple:

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

b     =  10011100
-----------------
b>>1 --> 01001110
b<<1 --> 10011100

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 réelle, modulo est plus lent , et de manière significative. Le gagnant, de loin, nécessitant 67% du temps de modulo, est une approche ou (|) et est introuvable 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 temps de référence sont les suivants.

3.962 la | et approche du masque

4.851 le & ampli; approche

5.850 l'approche%

Pour les personnes qui pensent que la théorie, ou une liste en langage assemblé, règle des arguments comme ceux-ci, cela 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 a donné

Ceci fait suite à la discussion avec @RocketRoy concernant sa réponse , mais elle pourrait être utile à quiconque veut 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 être x & 1 identique à l'approche mod, mais, dans la pratique, les temps devraient être plus longs. égaux dans tous les cas.

J'ai donc d'abord comparé la sortie compilée à l'aide de Explorateur du compilateur :

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

Classe 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 à Clang, il s'est rendu compte que les trois cas sont fonctionnellement égaux. Toutefois, l'approche de Roy n'est pas optimisée dans GCC, donc YMMV.

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

// 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é).

L'assembly de publication utilise l'instruction test pour les cas and et cmp eax,0FFFFFFFFh, tandis que le cas de Roy utilise l'approche #if LINUX, mais il est fortement déroulé et optimisé, 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 ] AVERAGE TIME: 689.29 ms (Relative diff.: +0.000%)
[Test: Bitwise or  ] AVERAGE TIME: 689.63 ms (Relative diff.: +0.048%)
[Test: Bitwise and ] AVERAGE TIME: 687.80 ms (Relative diff.: -0.217%)

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

Voici le code si quelqu'un veut essayer, en précisant que je ne l'ai testé que sous Windows (vérifiez la get_time conditionnelle pour la définition <=> et implémentez-la si nécessaire, tirée de cette 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;
}

Je sais que c'est juste du sucre syntaxique et uniquement 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);
    }
}

Vous pouvez maintenant effectuer les opérations suivantes

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

Dans la ". catégorie créative mais source de confusion " J'offre:

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

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 en réalité les bits de bas niveau pour le balisage (comme les langages dynamiques), donc raw x & Amp; 1 ne fonctionnera pas réellement dans ce cas.

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 cette procédure pour les entiers négatifs, sauf chercher le plus grand nombre non impair.

Portable:

i % 2 ? odd : even;

Unportable:

i & 1 ? odd : even;

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

Comme certains l’ont indiqué, il existe de nombreuses façons de le faire. Selon ceci 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é par l'auteur et 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 le Math.System.DivRem ou pourquoi l’utiliseraient-ils?

int isOdd(int i){
  return(i % 2);
}

terminé.

Pour expliquer plus en détail la méthode de l’opérateur binaire 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ération, mais j’ai eu envie de préciser pourquoi NUMBER & Amp; 1 œuvres.

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 fonctionne bien.

Comme Tooony ci-dessus a fait remarquer 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 haute tension) pour que 1 soit renvoyée.

1 & amp; 0 = 0.

0 & amp; 1 = 0.

0 & amp; 0 = 0.

1 & amp; 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 ET au niveau du bit AND (& amp; en java), il renvoie 1 par 0, soit 00000001, = 1, ce qui signifie que le nombre est impair. Ou 00000000 = 0, ce qui signifie que le nombre est pair.

E.g

Est-ce étrange?

1 & amp; 1 =

00000001 & amp;

00000001 =

00000001 < & # 8212; Bizarre

2 & amp; 1 =

00000010 & amp;

00000001 =

00000000 < & # 8212; Même

54 & amp; 1 =

00000001 & amp;

00110110 =

00000000 < & # 8212; Même

C'est pourquoi cela fonctionne:

if(number & 1){

   //Number is odd

} else {

   //Number is even
}

Désolé si cela est redondant.

Numéro 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))
  

Résultat:

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

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 que la fraction du résultat manque 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 & "Plus lisible &"; code.

Nous pourrions rendre tout cela 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 plus difficile à maintenir dans le futur. Imaginez simplement que vous souhaitiez changer le texte des nombres impairs en & "; N’est même pas &"; 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 préoccupé par la portabilité mais par la vitesse, vous pouvez jeter un coup d'œil au bit le moins significatif. 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 système endian, comme l’architecture x86 d’Intel, cela ressemblerait à ceci: -

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

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

Vérifier les paires de points de contrôle ou impairs est une tâche simple.

  

Nous savons qu'un nombre exactement divisible par 2 est un nombre pair, sinon un nombre impair.

Il suffit de vérifier la divisibilité d'un nombre quelconque et pour vérifier la divisibilité, nous utilisons un % opérateur

.

Vérification des valeurs impaires avec if if else

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

Programme en C pour vérifier les paires de niveaux, en utilisant if sinon

Utilisation de l'opérateur Conditionnel / Ternaire

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

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

Utilisation de l'opérateur Bitwise

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

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

Notez que le bit le plus à droite a toujours la valeur 1 pour les chiffres impairs .

l'opérateur & amp; AND au niveau du bit AND vérifie si le bit le plus à droite de notre ligne Renvoyer est 1

Considérez-le comme vrai & amp; 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 de 1 octet.

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

Si l'int n était le 7 et que nous le comparions à 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

Quel F correspond à false et T à true.

  

Il compare uniquement le bit le plus à droite s'il est vrai. Donc, automatiquement 7 & amp; 1 est T rue.

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

Modifiez simplement n & amp; 1 à n & amp; 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 dans les opérations au niveau des bits

retourne n & amp; 1; > > retourne n & amp; 0x01; .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top