Je regarde du code qui devrait être trivial - mais mes calculs me font lamentablement défaut ici.
Voici une condition qui vérifie si un nombre est une puissance de 2 en utilisant ce qui suit:
if((num != 1) && (num & (num - 1))) { /* make num pow of 2 */ }
Ma question est de savoir comment l'utilisation d'un ET au niveau du bit entre num et num - 1 détermine si un nombre est une puissance de 2?
Toute puissance de 2 moins 1 est tout entière: ( 2 N - 1 = 111 .... b )
2 = 2^1. 2-1 = 1 (1b)
4 = 2^2. 4-1 = 3 (11b)
8 = 2^3. 8-1 = 7 (111b)
Prenez 8 par exemple. 1000 et 0111 = 0000
Cette expression teste donc si un nombre n'est PAS une puissance de 2.
Eh bien, le premier cas vérifiera 2 == 1.
Pour les autres cas, la num & (num - 1)
entre en jeu:
Cela signifie que si vous prenez un nombre et masquez les bits d'un inférieur, vous obtiendrez l'un des deux cas:
si le nombre est déjà une puissance de deux, alors un de moins se traduira par un nombre binaire qui n'a que les bits de poids faible définis. En utilisant &
, Il n'y aura rien.
0100 & (0100 - 1)
-> (0100 & 0011)
-> 0000
si le nombre n'est pas déjà une puissance de deux, alors un de moins ne touchera pas le bit le plus élevé, donc le résultat sera au moins la plus grande puissance de deux de moins que num.
Exemple avec 3: 0011 & (0011 - 1)
-> (0011 & 0010)
-> 0010
Exemple avec 13: 1101 & (1101 - 1)
-> (1101 & 1100)
-> 1100
Ainsi, l'expression réelle trouve tout ce qui n'est pas un pouvoir de deux, y compris 2.
Bien,
si vous avez X = 1000, alors x-1 = 0111. Et 1000 && 0111 est 0000.
Chaque nombre X qui est une puissance de 2 a un x-1 qui en a sur la position x a des zéros. Et un bit à bit et de 0 et 1 est toujours 0.
Si le nombre x n'est pas une puissance de deux, par exemple 0110. Le x-1 est 0101 et le et donne 0100.
Pour toutes les combinaisons entre 0000 et 1111, cela conduit à
X X-1 X && X-1
0000 1111 0000
0001 0000 0000
0010 0001 0000
0011 0010 0010
0100 0011 0000
0101 0100 0100
0110 0101 0100
0111 0110 0110
1000 0111 0000
1001 1000 1000
1010 1001 1000
1011 1010 1010
1100 1011 1000
1101 1100 1100
1110 1101 1100
1111 1110 1110
Et il n'est pas nécessaire d'effectuer un contrôle séparé pour 1.
Expliqué ici bien
De plus, l'expression donnée considère 0 comme une puissance de 2. Pour résoudre ce problème, utilisez !(x & (x - 1)) && x;
à la place.
Il détermine si l'entier est une puissance de 2 ou non. Si (x & (x-1))
est zéro alors le nombre est la puissance de 2.
Par exemple, laissez x
être 8 (1000
en binaire); puis x-1
= 7 (0111
).
if 1000
& 0111
---------------
0000
Programme C pour démontrer:
#include <stdio.h>
void main()
{
int a = 8;
if ((a&(a-1))==0)
{
printf("the bit is power of 2 \n");
}
else
{
printf("the bit is not power of 2\n");
}
}
Cela génère the bit is power of 2
.
#include <stdio.h>
void main()
{
int a = 7;
if ((a&(a-1))==0)
{
printf("the bit is power of 2 \n");
}
else
{
printf("the bit is not power of 2\n");
}
}
Cela génère the bit is not power of 2
.