Tutoriel vidéo Algorithmique : Les opérateurs binaires

En regardant le code source de @preact/signals-core je suis tombé sur le code suivant.

// Flags for Computed and Effect.
const RUNNING = 1 << 0;
const NOTIFIED = 1 << 1;
const OUTDATED = 1 << 2;
const DISPOSED = 1 << 3;
const HAS_ERROR = 1 << 4;
const TRACKING = 1 << 5;

// ...
if (effect.flags & DISPOSED) { }

Ce n’est pas forcément un code qu’on a l’habitude de voir dans le développement web. Aussi je vous propose de décrypter ces opérateurs binaires et voir leur utilisation dans un cas concret.

Opérateur de décalage <<

L’opérateur de décalage à gauche << est un opérateur binaire qui décale les bits d’un nombre vers la gauche d’un certain nombre de positions.

Binaire
1 0000 0001
1 << 0 0000 0001
1 << 1 0000 0010
1 << 2 0000 0100

Dans le cas de l’exemple, l’opérateur est utilisé pour créer des nombre binaires avec le bit 1 décalé d’un certain nombre sur la gauche.

Opérateur OR |

L’opérateur binaire OR retourne vrai (1) si au moins l’une des deux valeurs est vraie (1).

A B A OR B
0 0 0
0 1 1
1 0 1
1 1 1

Dans le cas de notre code, cet opérateur va permettre de créer une variable qui combine plusieurs valeurs.

const LOG = 1 << 0
const WARN = 1 << 1
const ERROR = 1 << 2

const flag = ERROR | WARNING

Opérateur AND &

L’opérateur binaire AND retourne vrai (1) si les des deux valeurs sont vraies (1).

A B A AND B
0 0 0
0 1 0
1 0 0
1 1 1

Dans le cas de notre code, cet opérateur va être utilisé dans une condition

if (flag & WARNING) {
    // Le drapeau contient WARNING
}

Opérateur NOT ~

L’opérateur binaire NOT inverse les bits.

Nombre Bits.
10 0000 1010
~10 1111 0101

Dans le cas du code il peut être utilisé en combinaison de l’opérateur & pour retirer un élément dans notre drapeau.

flag &= ~WARNING

Analogie avec l’approche tableau

Pour résumer les opérateurs binaires peuvent être utilisés en remplacement d’une liste pour gérer une liste d’état / drapeau. L’opérateur OR est utilisé pour combiner plusieurs valeurs en une seule.

// En binaire
flag = WARNING | ERROR

// En tableau
flag = ["WARNING", "ERROR"]

Cet opérateur peut aussi être utilisé lors d’un assignement pour ajouter une valeur.

// En binaire
flag |= WARNING

// En tableau
flag.push("WARNING")

L’opérateur AND va servir à vérifier la présence d’une valeur dans notre drapeau.

// En binaire
if (flag & WARNING) { }

// En tableau
if (flag.includes("WARNING")) { }

Enfin la combinaison de l’opérateur NOT et AND permet de retirer facilement une valeur dans le drapeau.

// En binaire
flag &= ~WARNING

// En tableau
flag = flag.filter(v => v !== "WARNING")

Pourquoi ?

L’utilisation des opérateurs binaire permet de sauvegarder l’information dans un espace mémoire plus réduit en n’utilisant qu’un octet pour sauvegarder une combinaison de valeurs mais on notera plusieurs petits inconvénients.

  • Cette approche marche bien si on a moins de 8 valeurs possible pour notre drapeau
  • Le déboggage peut être un peu plus difficile avec un nombre plutôt qu’une chaine de caractère.