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