Opérations bit à bit, ou bitwise operations en anglais.
Les opérations bit à bit sont des calculs sur les bits qui utilisent l’algèbre de Boole: NOT, AND, OR, XOR et décalages.
Les opérations sur les bits sont très utiles en programmation pour gérer des listes d’options (multiples de 2):
<?php
define('UAG_OPTION1', 1); # 001
define('UAG_OPTION2', 2); # 010
define('UAG_OPTION3', 4); # 100
function hasOption($config, $opt) {
return ($config & $opt) > 0;
}
function removeOption($config, $opt) {
return ($config & ~$opt);
}
function addOption($config, $opt) {
return ($config | $opt);
}
$opts = UAG_OPTION1; # 001
$opts = addOption($opts, UAG_OPTION2); # 011
$opts = addOption($opts, UAG_OPTION3); # 111
$opts = removeOption($opts, UAG_OPTION2); # 101
NB Il n’est pas nécessaire d’apprendre par coeur tous les multiples de 2 !
Connaître 1,2,4,8 puis utiliser la notation hexadécimale :
Valeur | Représentation binaire |
---|---|
1 | 1 |
2 | 10 |
4 | 100 |
8 | 1000 |
0x10 | 10000 |
0x20 | 100000 |
0x40 | 1000000 |
0x80 | 10000000 |
0x100 | 100000000 |
Négation: les bits qui sont positionnés à 1 dans a
sont positionnés à 0, et vice-versa
NOT 0111
= 1000
En programmation:
~
permet d’inverser.
~~
est parfois utilisé comme substitut de Math.floor
~~'-1' = -1
~~true = 1
~~false = 0
~~5.6 = 5
Et logique: les bits positionnés à 1 dans a
ET b
sont positionnés à 1
0101
AND 0011
= 0001
En programmation:
&
(and) permet de tester la valeur d’un bit ou, avec la négation, de supprimer des bits.
<?php
error_reporting(E_ALL & ~E_NOTICE); ## Afficher toutes les erreurs SAUF les notices
if(error_reporting() & E_NOTICE) {
echo "Reporting of Notices is on";
} else {
echo "Reporting of Notices is off";
}
& 1
est parfois utilisé pour vérifier la parité d’un nombre
<?php
if($n & 1) {
echo "ODD!";
} else {
echo "EVEN!";
}
Ou logique: les bits positionnés à 1 dans a
OU b
sont positionnés à 1
0101
OR 0011
= 0111
En programmation:
|
(or) permet d’ajouter
<?php
error_reporting(E_ERROR | E_RECOVERABLE_ERROR); # Afficher les erreurs ET les erreurs recouvrables
Ou exclusif: Les bits positionnés à 1 dans a
OU b
MAIS PAS LES DEUX sont positionnés à 1
0101
XOR 0011
= 0110
En programmation:
^
(xor) permet de retirer un bit s’il est vrai, de l’ajouter s’il est faux (= toggle).
<?php
$hasOption3 = $opts & UAG_OPTION3;
if($hasOption3) {
$opts = ($opts ^ UAG_OPTION3); # Enleve UAG_OPTIONS3
} else {
$opts = ($opts ^ UAG_OPTION3); # Ajoute UAG_OPTIONS3
}
^
est parfois utilisé pour permuter deux variables sans utiliser d’emplacement mémoire supplémentaire
<?php
$a = 11;
$b = 22;
$a = $a ^ $b;
$b = $a ^ $b;
$a = $a ^ $b;
echo $a . " " . $b; // 22 11
Le décalage à gauche décale tous les bits vers la gauche, ce qui revient à une multiplication par 2 pour un décalage de 1 (2^1), 4 pour un décalage de 2 (2^2), 8 pour un décalage de 3 (2^3), etc.
00010111 (+23) LEFT-SHIFT
= 00101110 (+46)
En programmation:
<<
(left shift) permet de multiplier par des puissances de 2 très rapidemment
<?php
function listOptions($opts) {
$nb = 3; # Nombre d'options possibles
$n = pow(2, $nb-1); # Valeur de la dernière option ($nb-1 puissance 2)
// Parcours multiples de 2 (multiplication)
$j = 1;
for($i = 1; $i <= $n; $i <<= 1) {
echo ($opts & $i ? '1' : '.');
}
echo '<br>';
}
listOptions(UAG_OPTION1); # 1..
listOptions(UAG_OPTION1 | UAG_OPTION2); # 11.
listOptions(UAG_OPTION1 | UAG_OPTION2 | UAG_OPTION3); # 111
Le décalage à droite décale tous les bits vers la droite, ce qui revient à une division par 2 pour un décalage de 1 (2^1).
00010111 (+23) RIGHT-SHIFT
= 00001011 (+11)
En programmation:
>>
(right shift) permet de diviser par 2 très rapidemment
<?php
function listOptions($opts) {
$nb = 3;
// Parcours incrémental + division sur variable cible
for($i = 1; $i <= $nb; $i++) {
echo $i . ':' . ($opts & 1 ? 'x' : '.') . ' ';
$opts >>=1 ;
}
echo '<br>';
}
listOptions(UAG_OPTION1); # 1..
listOptions(UAG_OPTION1 | UAG_OPTION2); # 11.
listOptions(UAG_OPTION1 | UAG_OPTION2 | UAG_OPTION3); # 111