Programmation JavaScript/Opérateurs de bits

Opérations binaires

modifier

Les opérations binaires correspondent à une manipulation bit à bit d'une valeur contenue dans un variable. Il est important de comprendre le procéder des opérations binaires avant de travailler avec ces dernières.

Représentation binaire

modifier

Un valeur contenue dans une variable est représenté côté machine par une succession de "0" et de "1". Chaque bit est placé à une position qui défini son poids et permet de cumuler les valeurs.

Le principe est en fait plus simple qu'il n'y parait. Prenons une donnée sur 4 bits:

0011

Ici, nous avons 4 colonnes qui représentent un bit chacun. Il faut lire les données de droite à gauche. La première colonne représente 2^0, le second 2^1, le troisième 2^2 et enfin la quatrième 2^3

Il suffit alors de cumuler les valeurs. Ici :

  1* 2^0 = 1
+ 1* 2^1 = 2
+ 0* 2^2 = 0
+ 0* 2^3 = 0

Soit : 3

La combinaison de 0 et 1 permet donc de représenter n'importe quel chiffre selon la taille en octet alloué à la variable. Sur 4 bit, on peut alors représenter au maximum le chiffre 1111 qui donne:

  1* 2^0 = 1
+ 1* 2^1 = 2
+ 1* 2^2 = 4
+ 1* 2^3 = 8

Soit : 15. En conséquence, en partant de 0, 4 bits représentent 16 valeurs possible allant de 0 à 15

Opérations

modifier

Il est possible de manipuler des valeurs binaire en utilisant des opérateurs spécifiques. Ainsi, il est possible de faire :

  • une opération "ou",
  • une opération "et",
  • une opération "ou exclusif",
  • un décalage de bits.

Les 3 premières opérations se font "bit à bit" à place respectives :

  • Le "et" vérifie si les deux bits valent "1". Dans ce cas, l'opération résulte d'un "1", sinon "0".
  • Le "ou" vérifie si un des bit est égal à "1" ou les deux. Dans ce cas, l'opération résulte d'un "1", sinon "0".
  • Le "ou" vérifie si un des bit est égal à "1" mais pas les deux. Dans ce cas, l'opération résulte d'un "1", sinon "0".

Ainsi, prenons un exemple: 9 et 12 (ne fait pas 9+12): 9 = 1001 12 = 1100

on regarde chaque colonne, et on opère avec un "et".

  • colonne 1 => 1 et 0 = 0
  • colonne 2 => 0 et 0 => 0
  • colonne 3 => 0 et 1 => 0
  • colonne 4 => 1 et 1 => 1

Résultat 1000 => 8

Le "ou" donne:

  • colonne 1 => 1 ou 0 = 1
  • colonne 2 => 0 ou 0 => 0
  • colonne 3 => 0 ou 1 => 1
  • colonne 4 => 1 ou 1 => 1

Résultat 1101 => 13

et enfin le ou exclusif:

  • colonne 1 => 1 xou 0 = 1
  • colonne 2 => 0 xou 0 => 0
  • colonne 3 => 0 xou 1 => 1
  • colonne 4 => 1 xou 1 => 0

Résultat 0101 => 5

Limitation

modifier

 

Les opérations se font sur 32 bits.

Les autres bits sont ignorés.

Exemple :

0x100000007 >> 1  /*   ==  3  car seuls les bits 31 à 0 sont pris en compte.  */

Utilité

modifier

On se sert d'opérations binaires dans beaucoup de cas, notamment pour le chiffrement, ou encore des opérations optimisées en mathématiques. Elles sont aussi utilisées pour manipuler les ensembles d'items dont le nombre d'instances est limité (énumération) représentés sous la forme d'un entier ou un bit à 1 représente la présence d'un item, et 0 son absence.

Il est à noter que répéter deux fois un "ou exclusif" revient à revenir à la valeur d'origine. Exemple :

Valeur 5 => 0101

Appliquons deux fois le ou exclusif avec 4 = 0100

    0101 => valeur initiale  5
xou 0100 => ou exclusif avec 4
    0001 => 1
xou 0100 => encore avec 4
    0101 = valeur 5, retour à l'état initial

Les opérateurs

modifier

Il existe plusieurs opérateurs qui permettent ces opérations.

  • & - "ET" (and)
  • | - "OU" (or)
  • ^ - "OU Exclusif" (xor)

Ainsi en javascript:

var a = 5
var b = 4
alert(a&b) /*Affiche 4*/
alert(a|b) /*Affiche 5*/
alert(a^b) /*Affiche 1*/

Manipulation sur chaîne de caractères

modifier

L'opération binaire ne se faisant que sur des entiers, il est nécessaire de connaitre le code ASCII des caractères sur lesquels nous voulons opérer. Il suffit d'utiliser la méthode "charCodeAt()" qui retourne le code ASCII à la position donnée.

Ainsi

var a="a"
//on récupère le code ASCII à l'index "0" => premier caractère
alert(a.charCodeAt(0)) //affiche 97

Cela permet dont de faire une opération binaire sur une chaine:

//hello et world ont la même taille, c'est important pour cet exemple.
var a="hello"
var b="world"
var buffer = []
//cela va faire h^w, e^o, l^r, l^l; o^d
for (var i=0; i<a.length; i++) {
     buffer.push ( a.charCodeAt(i)^b.charCodeAt(i) )
}
alert ( buffer.join(':') ) //31:10:30:0:11

var result = ""
//opération inverse, revient à "hello"
for (var i=0; i<a.length; i++) {
     result += String.fromCharCode(buffer[i] ^ b.charCodeAt(i))
}
alert(result) //hello

Décalage de bits

modifier