Programmation JavaScript/Opérateurs de bits
Opérations binaires
modifierLes 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
modifierUn 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
modifierIl 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é
modifierOn 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
modifierIl 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
modifierL'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