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