web-dev-qa-db-fra.com

Incrémentation des ensembles de bits «masqués»

Je suis actuellement en train d'écrire un énumérateur d'arbre où j'ai rencontré le problème suivant:

Je regarde des ensembles de bits masqués, c'est-à-dire des ensembles de bits où les bits définis sont un sous-ensemble d'un masque, c'est-à-dire 0000101 avec masque 1010101. Ce que je veux accomplir, c'est incrémenter le jeu de bits, mais uniquement en ce qui concerne les bits masqués. Dans cet exemple, le résultat serait 0010000. Pour le rendre un peu plus clair, extrayez uniquement les bits masqués, c'est-à-dire 0011, incrémentez-les à 0100 et les distribuer à nouveau aux bits de masque, donnant 0010000.

Quelqu'un voit-il un moyen efficace de le faire, à moins d'implémenter l'opération à la main en utilisant une combinaison de bitscans et de masques de préfixe?

78
Tobias Ribizel

Remplissez simplement les bits non masqués par ceux pour qu'ils se propagent:

// increments x on bits belonging to mask
x = ((x | ~mask) + 1) & mask;
120
zch

Bien que n'étant pas intuitif par rapport à la réponse acceptée, cela fonctionne en seulement 3 étapes:

x = -(x ^ mask) & mask;

Cela peut être vérifié comme suggéré par zch:

  -(x ^ mask)
= ~(x ^ mask) + 1  // assuming 2's complement
= (x ^ ~mask) + 1
= (x | ~mask) + 1  // since x and ~mask have disjoint set bits

Elle devient alors équivalente à la réponse acceptée.

19
nglee

Si l'ordre d'itération n'est pas si important et qu'une opération de décrémentation satisfera vos besoins, il est possible d'utiliser seulement deux opérations:

Commençons avec

x = mask

et obtenez la valeur précédente avec

x = (x - 1) & mask

La partie x - 1 Change le dernier bit non nul en zéro et met tous les bits moins significatifs à 1. Ensuite, la partie & mask Ne laisse que des bits de masque parmi eux.

7
DAle