Opérateurs binaires - noelno/dovelei GitHub Wiki
Source : https://code.tutsplus.com/articles/understanding-bitwise-operators--active-11301
Opérateur & (ET binaire)
Compare les bits occupés par chaque valeur.
Exemple : 23 & 37
23 : 00010111
37 : 00100101
Le & binaire compare les bits de la même rangée, et vérifie s'ils valent tous les deux un. Si c'est le cas, la même rangée dans le résultat vaut 1.
23 : 00010111
37 : 00100101
Résultat : 00000101
(5 en décimal)
La comparaison 23 & 37
retourne donc 5.
Intérêt : plus performant pour savoir si une valeur est paire de faire $valeur & 1
que de faire $valeur % 2
.
(un nombre impair en binaire a toujours son dernier bit à 1 - tous les autres bits correspondent à des puissances de 2 donc sans le dernier bit à 1 le résultat sera toujours pair. $valeur & 1
retourne 1 si le dernier bit vaut 1, sinon 0)
Opérateur | (OU binaire)
Exemple : 23 | 37
23 : 00010111
37 : 00100101
Dans cet exemple on compare les bits de la même rangée, et on vérifie si au minimum l'un des deux vaut 1.
Si c'est le cas, la même rangée dans le résultat vaut 1.
23 : 00010111
37 : 00100101
Résultat : 00110111
(55 en décimal)
Intérêt : utile dans un système de flag.
j'ai une fonction qui fait 4 choses différentes selon les valeurs de 4 booléens qui lui sont passés en paramètre.
Plutôt que de passer 4 booléens en paramètre, on peut passer un seul integer en paramètre, et utiliser les bits comme booléens.
Par exemple si je passe 5 en paramètre, cela donne 0000101
en bits. Je peux me servir des 4 dernières rangées (0101) comme booléens.
Concrètement la valeur 5 signifie que le premier paramètre est à FALSE, le deuxième à TRUE, le troisième à FALSE et le quatrième à TRUE.
Pour récupérer informatiquement la valeur de chaque paramètre, je n'ai qu'à comparer mon 5 avec l'opérateur &
:
- 5 & 8 //8 = 1000 en bits
- 5 & 4 //4 = 0100 en bits
- 5 & 2 //2 = 0010 en bits
- 5 & 1 //1 = 0001 en bits
Pour chaque comparaison, si le bit attendu ne vaut pas 1
, le résultat final vaudra 0
.
public class PopupWindow extends Sprite
{
public static const YES:int = 1;
public static const NO:int = 2;
public static const OKAY:int = 4;
public static const CANCEL:int = 8;
public static void showPopup(buttons:int)
{
if(buttons & YES)
{
// add YES button
}
if(buttons & NO)
{
// add NO button
}
}
Comment détermine t-on la valeur 5 de départ ?
PopupWindow.show(PopupWindow.YES | PopupWindow.NO | PopupWindow.CANCEL);
L'opérateur | nous permet de cumuler les bits : YES
active le bit tout à droite, CANCEL
active le bit tout à gauche…
Note : ce système est utilisé pour le choix des options d'affichage d'erreur en PHP :
error_reporting(E_ERROR | E_RECOVERABLE_ERROR);
Cette approche combine E_ERROR
00000000000000000000000000000001
et E_RECOVERABLE_ERROR
00000000000000000001000000000000
Avec l'opérateur OR (|) pour s'assurer que
les bits sont activés dans l'une ou l'autre valeur :
00000000000000000001000000000001
L'opérateur ~
Equivalent du !
logique : tous les bits prennent la valeur opposée.
37 : 00100101
~37 : 11011010
Le premier bit à gauche est le bit de signe, il ne compte pas dans le calcul des bits.
Pour convertir ~37 en décimal, on remplace le bit de signe par le signe (- pour 1, + pour 0), on ajoute 1 au résultat, ce qui donne -1011011
, et donc -37.
Intérêt : permet de trouver la valeur négative d'un nombre
L'opérateur ^ (OU exclusif)
Équivaut au XOR logique : on compare les bits de la même rangée, et on vérifie si l'un des deux vaut 1 (mais pas les deux, contrairement à |). Si c'est le cas, la même rangée dans le résultat vaut 1.
L'opérateur << (left bitshift)
Décale les bits sur la gauche de x rangs (ici 3).
37 : 00100101
37 << 3 : 00101000
L'espace libéré sur la droite est remplacé par des zéros.
Cette opération équivaut à multiplier 37 par 2 puissance 3.
L'opérateur >> (right bitshift)
Décale les bits sur la droite de x rangs.
37 : 00100101
37 << 3 : 00000100
L'espace libéré est rempli par des zéros si le bit de signe (le bit le plus à gauche) est un zéro, ou par des 1 si le signe de bit est un 1.
Cette opération équivaut à diviser 37 par 2 puissance 3.
L'opérateur >>> (unsigned right bitshift)
Décale les bits sur la droite de x rangs.
37 : 00100101
37 << 3 : 00000100
L'espace libéré est rempli par des zéros dans tous les cas. Le résultat est donc toujours positif.
Cette opération équivaut à diviser 37 par 2 puissance 3.
Exemple d'application : traitement des couleurs en RGB
Notre couleur est un vert émeraude : #2bb24c
RRRRRRRR GGGGGGGG BBBBBBBB
00101011 10110010 01001100 //#2bb24c converti en binaire
Pour récupérer le bleu : 0x2bb24c & 0x0000FF
(masque sur la zone correspondant au bleu. 0x0000FF
peut aussi s'écrire 0xFF
)
Pour récupérer le vert : 0x2bb24c & 0x00FF00 >> 8
(8
correspond au nombre de bits après le vert, ceux du bleu. Comme on ne récupère que le vert, on vire l'espace occupé par le bleu)
Pour récupérer le rouge : 0x2bb24c & 0x00FF00 >>> 16
(ici on utilise >>>
plutôt que >>
car on est tout à gauche, le signe de bit pourrait être négatif mais on attend un résultat positif)
Pour composer sa propre couleur : uint(($r << 16) | ($g << 8) | $b)
Les opérateurs combinés
x &= 0xFF
équivaut àx = x & 0xFF
x |= 256
équivaut àx = x | 256