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?

Utilisez l’opérateur modulo (%) pour vérifier s’il y a un rest 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 & 1 est “plus rapide” ou “plus efficace”. Je ne crois pas que ce soit le cas.

Par curiosité, j’ai créé deux programmes de tests simples:

 /* modulo.c */ #include  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  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 resockets différentes:

  • Sans indicateur d'optimisation.
  • Avec -O
  • Avec -Os
  • Avec -02
  • 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 pour and.c et modulo.c étaient identiques (ils utilisaient tous deux l'instruction andl $ 1,% eax). Je doute que ce soit une "nouvelle" fonctionnalité, et je pense que cela remonte à des versions anciennes. Je doute aussi que tout compilateur moderne (fabriqué au cours des 20 dernières années), sans arcane, commercial ou open source, 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 voulait tester d'autres compilateurs et / ou des 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 par 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. La version binary et la version ne sont pas. Oui, je réalise que le complément à deux est quelque peu omniprésent, donc ce n’est pas vraiment un problème.

Vous êtes waaaaaaaay 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 pour isEven .

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

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.

[Mode blague = “on”]

 public enum Evenness { Unknown = 0, Even = 1, Odd = 2 } public static Evenness AnalyzeEvenness(object o) { if (o == null) return Evenness.Unknown; ssortingng foo = o.ToSsortingng(); if (Ssortingng.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 confuses à l’énumération.

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 non , cela ne fonctionne 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 à 2
  • Complément à 1
  • signe et magnitude

Vérification comme ceci:

 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 crois que ce qui suit fonctionnera dans tous les cas:

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

Merci à ffpf pour avoir souligné que la boîte de texte mangeait tout après mon moins grand caractère!

Une belle est:

 /*forward declaration, C comstacks 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 la queue impliquant 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 de la queue comme un compilateur Scheme. Dans ce cas, la stack ne doit pas déborder!

Un nombre est même si, divisé par deux, le rest est égal à 0. Un nombre est impair si, divisé par 2, le rest 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 juste le diviser par 2 et s’il rest un 0, c’est pair, sinon c’est bizarre.

Utiliser le module (%) rend cela facile.

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 une table des parités (0 si même 1 si impair) des 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]; } 

Alors, à la place, 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-entiers les valeurs possibles de int dans une compilation C donnée. (Notez que les entiers C sont un sous-ensemble des entiers.)

Maintenant, on pourrait s'inquiéter du fait que pour un entier n en C donné, l'entier correspondant k pourrait ne pas exister dans les entiers C. 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 une des prises suivantes (exactement les cas (1 et 2) ou les cas (3 et 4) en fait, mais je ne le prouverai pas 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 est pas encore, la boucle ne retourne even pas tôt, donc ça n’a pas d’importance.) Mais cela implique k even , donc k = 0 est en C-entiers). Ainsi, un tel ak dans les entiers C existe pour n dans les entiers C si n est pair.

Un argument similaire montre que si n est impair, il existe ak dans les entiers C tels que n = 2k + 1.

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

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

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 un autre code qui a été marqué par l’auteur et qui a été exécuté plus lentement que l’opération de module commune 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.ToSsortingng(); 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?

Voici une réponse en Java:

 public static boolean isEven (Integer Number) { Pattern number = Pattern.comstack("^.*?(?:[02]|8|(?:6|4))$"); Ssortingng num = Number.toSsortingng(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 souvenu que j’avais une fonction réelle, sensible au temps, qui testait les nombres pairs et impairs dans la boucle principale. C’est une fonction de puissance entière, publiée ailleurs sur StackOverflow, comme suit. Les benchmarks étaient assez surprenants. Au moins dans cette fonction du monde réel, modulo est plus lent et de manière significative. Le gagnant, avec une marge importante, nécessitant 67% du temps de modulo, est une approche ou (|) , et ne se trouve nulle part 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 délais de référence sont les suivants.

3.962 le | et approche de masque

4.851 l’approche &

5.850 l’approche%

Pour les personnes qui pensent que la théorie, ou un listage en langage d’assemblage, règle des arguments comme ceux-ci, cela devrait être une mise en garde. Il y a plus de choses au ciel et sur la terre, Horatio, que ce dont on rêve dans votre philosophie.

Ceci fait suite à la discussion avec @RocketRoy concernant sa réponse , mais elle pourrait être utile à quiconque souhaite 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 approche mod , mais dans la pratique, les temps d’exécution devraient être égaux dans tous les cas.

Donc, j’ai d’abord comparé la sortie compilée en utilisant Comstackr 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)); } 

CLang 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 à 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, alors YMMV.

C’est similaire avec Visual Studio; inspectant la version x64 de désassemblage (VS2015) pour ces trois fonctions, je pouvais voir que la partie de comparaison est égale pour les cas “mod” et “et”, et légèrement plus grande pour le cas “ou” du Roy:

 // 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 avoir exécuté un benchmark pour comparer ces trois options (mod simple, bitwise ou bitwise), les résultats étaient complètement identiques (encore une fois, Visual Studio 2005 x86 / x64, version Release, aucun débogueur attaché).

Release assemblage utilise les instructions de test pour and et mod tandis que le cas de Roy utilise l’approche cmp eax,0FFFFFFFFh , mais il est fortement déroulé et optimisé, il n’y a donc pas de différence dans la pratique.

Mes résultats après 20 exécutions (i7 3610QM, plan d’alimentation Windows 10 défini sur High Performance):

 [Test: Mod mod 2] TEMPS MOYEN: 689,29 ms (Diff .: + 0,000%)
 [Test: bit à bit ou] TEMPS MOYEN: 689,63 ms (diff relatif: + 0,048%)
 [Test: bit à bit et] TEMPS MOYEN: 687.80 ms (diff relatif: -0.217%)

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

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

 #include  #if LINUX #include  #include  double get_time() { struct timeval t; struct timezone tzp; gettimeofday(&t, &tzp); return t.tv_sec + t.tv_usec*1e-6; } #else #include  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 seulement applicable dans .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... } 

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

La méthode binary 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 effectivement les bits de bas niveau pour le marquage (comme les langages dynamics), de sorte que le raw x & 1 ne fonctionnera pas dans ce cas.

IsOdd (int x) {renvoie true; }

Preuve de justesse – considérons l’ensemble de tous les entiers positifs et supposons qu’il existe un ensemble non entier d’entiers 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 pour rechercher le plus grand nombre non impair.

Portable:

 i % 2 ? odd : even; 

Inutilisable:

 i & 1 ? odd : even; i << (BITS_PER_INT - 1) ? odd : even; 
 int isOdd(int i){ return(i % 2); } 

terminé.

Pour donner plus de détails sur la méthode de l’opérateur bitwise pour ceux d’entre nous qui n’ont pas fait beaucoup d’algèbre booléenne au cours de nos études, voici une explication. Probablement pas très utile pour l’OP, mais j’ai eu envie de faire comprendre pourquoi NUMBER & 1 fonctionne.

Veuillez noter que, comme quelqu’un a répondu ci-dessus, la façon dont les nombres négatifs sont représentés peut empêcher cette méthode de fonctionner. En fait, il peut même casser la méthode de l’opérateur modulo puisque chaque langage peut différer dans la manière dont il traite les opérandes négatifs.

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

Comme Tooony ci-dessus fait remarquer que seul le dernier chiffre en binary (et le déni) est important.

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

1 & 0 = 0.

0 & 1 = 0.

0 & 0 = 0.

1 & 1 = 1.

Si vous représentez un nombre quelconque en binary (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 n’importe quel nombre et utilisez le bit AND (& in java), il renverra 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 &

00000001 =

00000001 <- Odd

2 & 1 =

00000010 &

00000001 =

00000000 <- Even

54 & 1 =

00000001 &

00110110 =

00000000 <- Even

C’est pourquoi cela fonctionne:

 if(number & 1){ //Number is odd } else { //Number is even } 

Désolé si c’est redondant.

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 
 I execute this code for ODD & EVEN: #include  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); } 

For the sake of discussion…

You only need to look at the last digit in any given number to see if it is even or odd. Signed, unsigned, positive, negative – they are all the same with regards to this. So this should work all round: –

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

The key here is in the third line of code, the division operator performs an integer division, so that result are missing the fraction part of the result. So for example 222 / 10 will give 22 as a result. Then multiply it again with 10 and you have 220. Subtract that from the original 222 and you end up with 2, which by magic is the same number as the last digit in the original number. 😉 The parenthesis are there to remind us of the order the calculation is done in. First do the division and the multiplication, then subtract the result from the original number. We could leave them out, since the priority is higher for division and multiplication than of subtraction, but this gives us “more readable” code.

We could make it all completely unreadable if we wanted to. It would make no difference whatsoever for a modern comstackr: –

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

But it would make the code way harder to maintain in the future. Just imagine that you would like to change the text for odd numbers to “is not even”. Then someone else later on want to find out what changes you made and perform a svn diff or similar…

If you are not worried about portability but more about speed, you could have a look at the least significant bit. If that bit is set to 1 it is an odd number, if it is 0 it’s an even number. On a little endian system, like Intel’s x86 architecture it would be something like this: –

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

If you want to be efficient, use bitwise operators ( x & 1 ), but if you want to be readable use modulo 2 ( x % 2 )

Checking even or odd is a simple task.

We know that any number exactly divisible by 2 is even number else odd.

We just need to check divisibility of any number and for checking divisibility we use % operator

Checking even odd using if else

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

C program to check even or odd using if else

Using Conditional/Ternary operator

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

C program to check even or odd using conditional operator .

Using Bitwise operator

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

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

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

The code checks the last bit of the integer if it’s 1 in Binary

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

Notice the rightmost bit is always 1 for Odd numbers.

the & bitwise AND operator checks the rightmost bit in our return line if it’s 1

Think of it as true & false

When we compare n with 1 which means 0001 in binary (number of zeros doesn’t matter).
then let’s just Imagine that we have the integer n with a size of 1 byte.

It’d be represented by 8-bit / 8-binary digits.

If the int n was 7 and we compare it with 1 , It’s like

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

Which F stands for false and T for true.

It compares only the rightmost bit if they’re both true. So, automagically 7 & 1 is T rue.

What if I want to check the bit before the rightmost?

Simply change n & 1 to n & 2 which 2 represents 0010 in Binary and so on.

I suggest using hexadecimal notation if you’re a beginner to bitwise operations
return n & 1; >> return n & 0x01; .