web-dev-qa-db-fra.com

Comment cette opération au niveau du bit vérifie-t-elle une puissance de 2?

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?

37
Coocoo4Cocoa

Toute puissance de 2 moins 1 est tout entière: ( 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.

91
eduffy

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:

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

    • Exemple avec 8: 0100 & (0100 - 1) -> (0100 & 0011) -> 0000
  2. 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.

14
lavinio

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.

6
Toon Krijthe

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.

3
rohittt

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.

1
sanjeev