INF280
Manipulation de bits
Antoine Amarilli
1/22
Introduction
• Données représentées sous la forme debits
• C++ permet de les manipulerdirectement
• Parfois plus rapide àexécuter
• Parfois plus rapide àécrire
Table des matières
Introduction Bases
Ensembles Nombres Autres
3/22
Opérations bit-à-bit
a & b • ETbit-à-bit
• Exemple : 01011101
& 00110101
= 00010101
a | b • OUbit-à-bit
• Exemple : 01011101
| 00110101
a ˆ b • XORbit-à-bit
• Exemple : 01011101 ˆ 00110101
= 01101000
˜ a • NOTbit-à-bit
• Exemple :
˜ 00110101
= 11001010
Décalage
a << i • Décalage vers lagauche(poids forts)
• Complèteavec0
• Peuttronquer
• Exemple :
01011101 << 2
= 01110100
a >> i • Décalage vers ladroite(poids faibles)
• Complèteavec0(sauf signe, voir plus tard)
• Peuttronquer
• Exemple :
01011101 >> 2
= 00010111
5/22
Builtinsgcc(non portable)
__builtin_popcount(s) Nombre de1
__builtin_ffs(s) Index du1le plus à droite (à partir de1)
• ffs(00000001) = 1
• ffs(00000110) = 2
• ffs(00000000) = 0
__builtin_clz(s) Index du1le plus à gauche (indéfini pour0)
• clz(10000001) = 0
• clz(01000110) = 1
• clz(00000000) = ?
Pièges
• Attention à lapriorité!
• a & b == 1
→ a & (b == 1)
• Attention auxgrands shifts!
• a << 1337estindéfini!
• Attention auxentiers signés!
7/22
Table des matières
Introduction Bases Ensembles
Nombres Autres
Principe
• Stocker unpetit ensembledans les bits d’un entier non-signé
• Lebitiest à1ssi l’élémentiest dans l’ensemble
→ Énumérerles ensembles en énumérant les entiers
→ Pluscompactqueset
→ Parfoisnécessairepour passer en temps/mémoire !
9/22
Types
• Dépend de lataillede l’ensemble :
• unsigned long longgarantit64 bits
• unsigned longgarantit32 bits
• unsignedgarantit16 bits
• Aussi :uint64_t,uint32_t,uint16_t,uint8_t (avec#include <cstdint>)
• Attentionà faire les bons casts !
uint64_t x = 1 << 33; // bug (comportement indéfini) uint64_t x = ((uint64_t) 1) << 33; // OK
Lecture de l’ensemble
s & t intersection s | t union
s ˆ t différence symétrique
s & (1 << i) teste si l’élémentiest dans l’ensemble __builtin_popcount(s) nombre d’éléments
__builtin_ffs(s) index du premier élément __builtin_clz(s) index du dernier élément
11/22
Modification de l’ensemble
s | (1 << i) ajouter l’élémenti s & ˜(1 << i) retirer l’élémenti
s ˆ (1 << i) basculer l’élémenti
s & (s-1) retirer le plus petit élément
Ensembles plus gros
• bitset<N>,taille fixe
→ remplace les entiers quand 64 ne suffit pas
• vector<bool>,taille variable
→ permet de changer la taille
→ overhead devector
13/22
Sous-ensemble
• Énumérer lessous-ensemblesdes
• Soitnle sous-ensemblecourant
• Idée :
• | ˜spourmettre à1les bits inutiles
• +1 pourpropagerune retenue
• & s pourremettre à0les bits inutiles
→ Prochain sous-ensemble:((n | ˜s) + 1) & s
Couples
• a * N + bpourencoder un couple
• p/Netp%Npourdécoder le couple
• Évidemmentil fautb<N
• Attention à lacapacité!
(Plutôt arithmétique que bit-à-bit...)
15/22
n-uplets
Plus de deux éléments :
// encode
long long v = 0;
for (int i = 0; i < n; i++) { v *= N;
v += p[i];
}
// décode
for (int i = n-1; i >= 0; i--) { q[i] = v % N;
v /= N;
Table des matières
Introduction Bases Ensembles Nombres
Autres
17/22
Complément à deux
• Entiernon signédenbits : de0à2nexclu
• Entiersigné: représenter des positifs et négatifs
• Premier bit : champ dusigne(0pour positif)
• Positifsde0à2n−1exclu
• Négatifs :
• De−1à−2n−1inclus
• Bit designeà1
• Autres bits :2n−abs(i)
→ Vrai en pratique maisnon garantipar le standard C++
Exemple de complément à deux
Valeur Non-signé Signé
0111 1111 127 127
0111 1110 126 126
· · · ·
0000 0001 1 1
0000 0000 0 0
1111 1111 255 -1
1111 1110 254 -2
· · · ·
1000 0001 129 -127
1000 0000 128 -128
19/22
Puissances de deux
• Tester sidivisible par 2:!(x & 1)
• Calculer2i:(1 << i)
• Tester sipuissance de 2:x && !(x & x-1)
• Doit contenir≥1bit à1
• Doit êtrenulsi premier bit à1est mis à0
→ Doit contenirexactement1 bit à1
Table des matières
Introduction Bases Ensembles Nombres Autres
21/22
Code de Gray
• Énumérerles valeurs de0à2nexclu
• Changerun seul bit à la fois
• Cas 1 :0,1
• Cas 2 :00,01,11,10
• Récurrence :
• Construirele codeCn−1
• Construirele code miroirCn−1
• C’est également un code !
• C1nestCn−1en préfixant avec un0
• C2nestCn−1en préfixant avec un1
• CnestC1nCn2