Accès rapide :
La vidéo
Introduction au système binaire
Généralité
Les opérateurs binaires
L'opérateur binaire AND
L'opérateur binaire OR (le ou inclusif)
L'opérateur binaire XOR (le ou exclusif)
L'opérateur binaire NOT
Représentation des nombres négatifs
Les opérateurs Java relatifs aux opérations de base
Les opérateurs de décalage de bits
Les opérateurs d'affectation
Cette vidéo vous montre comment utiliser les différents opérateurs de manipulation de la représentation binaire de vos entiers. Elle montre aussi comment afficher un entier dans sa représentation binaire.
Nous l'avons vu dans un chapitre précédent, Java permet d'exprimer la valeur de vos entiers via différentes bases numériques (le binaire, l'octal, le décimal et l'hexadécimal). Dans allons, dans ce chapitre, porter notre attention sur la base numérique binaire : on parle aussi de système binaire.
En base binaire, on utilise uniquement deux chiffres : le 0 et le 1. Le tableau suivant vous présente quelques valeurs exprimées en binaire, mais aussi en décimal et en hexadécimal.
Valeur en binaire | Valeur en décimal | Valeur en hexadécimal |
---|---|---|
00000000 | 0 | 0 |
00000001 | 1 | 1 |
00000010 | 2 | 2 |
00000011 | 3 | 3 |
00000100 | 4 | 4 |
00000101 | 5 | 5 |
00000110 | 6 | 6 |
00000111 | 7 | 7 |
00001000 | 8 | 8 |
00001001 | 9 | 9 |
00001010 | 10 | A |
00001011 | 11 | B |
00001100 | 12 | C |
00001101 | 13 | D |
00001110 | 14 | E |
00001111 | 15 | F |
00010000 | 16 | 10 |
00100000 | 32 | 20 |
01000000 | 64 | 40 |
10000000 | 128 | 80 |
11111111 | 255 | FF |
Dans le système de numération binaire, un chiffre est appelé un bit. En électronique cette notion de bit est très importante car elle correspond à l'état électrique d'un fil électrique (en caricaturant) : 0 correspond à l'absence de courant sur ce fil et 1 correspond à la présence du courant sur ce fil. Il faut aussi noter que sur l'électronique actuellement utilisée dans nos ordinateurs, on utilise des transistors qui ne savent gérer que deux états : 0 ou 1.
Il est aussi à noter, qu'on a pris l'habitude, en électronique et donc en informatique, de regrouper les bits par blocs de 8. On appelle un tel ensemble un octet. Comme un octet est constitué de 8 bits et comme chacun de ces bits ne peut valoir que 0 ou 1 (2 états), cet octet peut donc avoir 256 états distincts (de 0 à 255).
Outre les opérations arithmétiques classiques (addition, soustraction, multiplication, division), le système binaire propose des opérateurs de manipulation de bits. Ces opérateurs sont appelés AND (le « et » binaire), OR (le « ou » binaire, aussi appelé « ou inclusif »), le XOR (le « ou exclusif » binaire) et le NOT (le « non » binaire, autrement dit la négation binaire). Ces operateurs travaillent sur une paire de bits, à l'exception du NOT qui travaille sur un unique bit.
Le tableau suivant précise le fonctionnement de l'opérateur AND.
AND | 0 | 1 |
---|---|---|
0 | 0 | 0 |
1 | 0 | 1 |
On peut appliquer cet opérateur sur deux valeurs complexes : pour chaque pair de bits, on calculera 1 si les deux bits de même position dans les deux valeurs considérées sont bien fixés à 1. Sinon, on calculera 0. Par exemple :
\ | Binaire | Décimal | Hexadécimal |
---|---|---|---|
Première valeur | 01010101 | 85 | 55 |
Seconde valeur | 11110000 | 240 | F0 |
AND | 01010000 | 80 | 50 |
Le tableau suivant précise le fonctionnement de l'opérateur OR.
OR | 0 | 1 |
---|---|---|
0 | 0 | 1 |
1 | 1 | 1 |
On peut appliquer cet opérateur sur deux valeurs complexes : pour chaque pair de bits, on calculera 1 si ou moins un des deux bits de même position dans les deux valeurs considérées est fixé à 1. Sinon, on calculera 0. Par exemple :
\ | Binaire | Décimal | Hexadécimal |
---|---|---|---|
Première valeur | 01010101 | 85 | 55 |
Seconde valeur | 11110000 | 240 | F0 |
OR | 11110101 | 245 | F5 |
Le tableau suivant précise le fonctionnement de l'opérateur XOR.
XOR | 0 | 1 |
---|---|---|
0 | 0 | 1 |
1 | 1 | 0 |
On peut appliquer cet opérateur sur deux valeurs complexes : pour chaque pair de bits, on calculera 1 si un seul des deux bits de même position dans les deux valeurs considérées est fixé à 1. Sinon, on calculera 0. Par exemple :
\ | Binaire | Décimal | Hexadécimal |
---|---|---|---|
Première valeur | 01010101 | 85 | 55 |
Seconde valeur | 11110000 | 240 | F0 |
XOR | 10100101 | 165 | A5 |
Le tableau suivant précise le fonctionnement de l'opérateur NOT.
Bit | NOT |
---|---|
0 | 1 |
1 | 0 |
On peut appliquer cet opérateur sur une valeur complexe : chacun de ses bits sera inversé. Par exemple :
\ | Binaire |
---|---|
Une valeur | 01010101 |
NOT de cette valeur | 10101010 |
En informatique les nombres signés sont gérés d'une manière particulière. Pour un type entier quelconque, le bit dit de point fort (celui le plus à gauche)
est appelé bit de signe. S'il est fixé à 1, on a alors à faire à une valeur négative. S'il est à 0, la valeur est donc considéré comme positive.
Dans l'exemple qui suit, on considère le type byte
du langage Java. Il occupe donc 1 octet, soit 8 bits. En fonction de l'état du
8ième bit, nous aurons donc à faire à une valeur positive ou négative.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public class Demo { public static void main( String [] args ) { byte value = (byte) 0b00001111; System.out.println( value ); // Affiche 15 value = (byte) 0b01000000; System.out.println( value ); // Affiche 64 value = (byte) 0b10000000; System.out.println( value ); // Affiche -128 value = (byte) 0b11111111; System.out.println( value ); // Affiche -1 int value2 = 0b10000000; System.out.println( value2 ); // Affiche 128, car le bit de signe d'un int est en position 32. } } |
byte
sont nécessaire car par défaut une valeur entière Java est typée int
. Il faut donc ramener les valeurs
du type int
vers byte
.
Cette représentation des nombres négatifs utilisée par Java est appelée « Complément à deux ». Cette représentation cherche à éviter d'avoir deux formes de la valeur 0 (signé ou non), contrairement à la représentation de type « complément à un ».
Il est maintenant temps de voir comment représenter les opérateurs vu précédemment (AND, OR, XOR et NOT) en Java. Le tableau suivant précise les caractères utilisés pour représenter chacun des opérateurs binaires considérés. Il est vrai qu'il est dommage que Java est récupéré ces caractères du langage C plutôt que d'utiliser des mots clés : c'est moins lisible, mais bon, c'est comme çà.
Opérateurs binaires | AND | OR | XOR | NOT |
---|---|---|---|---|
Opérateurs binaires Java | & | | | ^ | ~ |
Avant de procéder à nos premiers tests sur ces opérateurs, je voudrais répondre à cette question : comment vérifier les résultats qui vont être produits ?
Le mieux serait d'afficher les résultats sous forme binaire. Pour ce faire nous utiliserons la méthode Integer.toBinaryString
.
Voici un petit exemple d'utilisation, en notant bien que je cherche ici à remplir par la gauche avec des caractères 0
si la taille de
la chaîne de caractères produite est inférieure à 4.
1 2 3 4 5 6 7 8 9 10 11 12 |
public class Demo { public static void main( String [] args ) { for( int i=0; i<16; i++ ) { String str = Integer.toBinaryString( i ); while( str.length() < 4 ) str = "0" + str; System.out.println( str ); } } } |
Voici les résultats produits par ce programme.
0000 0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111
Maintenant, testons ces fameux opérateurs binaires. Le programme suivant effectue quelques calculs grâce à eux.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class Demo { public static void main( String [] args ) { int value1 = 0b10101010; int value2 = 0b00001111; // & (AND) | (OR) ^ (XOR) ~ (NOT) System.out.println( "NOT - " + Integer.toBinaryString( ~value1 ) ); System.out.println( "AND - " + Integer.toBinaryString( value1 & value2 ) ); System.out.println( "OR - " + Integer.toBinaryString( value1 | value2 ) ); System.out.println( "XOR - " + Integer.toBinaryString( value1 ^ value2 ) ); } } |
Voici les résultats produits par ce programme.
NOT - 11111111111111111111111101010101 AND - 1010 OR - 10101111 XOR - 10100101
Java vous propose deux autres opérateurs permettant des décaler les bits d'un certain nombre de rangs. L'opérateur <<
permet de
décaler les bits vers la gauche, alors que l'opérateur >>
permet un décalage vers la droite. Dans les deux cas, l'opérande de droite
de l'opérateur (un opérande est en quelque sorte un paramètre de l'opérateur, mais utilisons les termes consacrés) correspond au nombre de rangs sur
lesquels opérer le décalage. Voici un petit exemple montrant ces possibilités.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public class Demo { public static void main( String [] args ) { int value = 0b00010001; // << (left shift) >> (right shift) System.out.println( "2 x << - " + Integer.toBinaryString( value ) + " -> " + Integer.toBinaryString( value << 2 ) + " [" + value + " -> " + (value << 2) + "]"); System.out.println( "2 x >> - " + Integer.toBinaryString( value ) + " -> " + Integer.toBinaryString( value >> 2 ) + " [" + value + " -> " + (value >> 2) + "]"); } } |
Voici les résultats produits par ce programme.
2 x << - 10001 -> 1000100 [17 -> 68] 2 x >> - 10001 -> 100 [17 -> 4]
Il faut aussi noter l'existance de l'opérateur >>>
. C'est un opérateur de décalage de bits à utiliser pour des valeurs que vous considérées
comme étant non signées. Du coup, des bits à zéro seront systématiquement insérés à droite. N'oubliez pas qu'en représentation signé, le bit de point le plus fort
correspond au signe de votre valeur numérique (0 == positif et 1 == négatif).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
package fr.koor.annotations; public class Start { public static void main( String[] args ) { int a = -8; // Manipulation en conservant le bit de signe System.out.printf( "-8 >> 1 == %d\n", (a >> 1) ); System.out.printf( "-8 >> 2 == %d\n", (a >> 2) ); // Manipulation en considérant la valeur comme étant non signée. System.out.printf( "-8 >>> 1 == %d\n", (a >>> 1) ); System.out.printf( "-8 >>> 2 == %d\n", (a >>> 2) ); } } |
Et voici les résultats produits par cet exemple :
-8 >> 1 == -4 -8 >> 2 == -2 -8 >>> 1 == 2147483644 -8 >>> 2 == 1073741822
Pour clore ce chapitre, notez que les opérateurs que nous venons d'étudier peuvent être cumulés à une affectation. Ainsi l'expression
a &= 0b1111
est équivalente à l'expression a = a & 0b1111
. Il en va de même pour les autres opérateurs proposés.
Voici la liste de toutes les combinaisons possibles avec un opérateur d'affectation.
Opérateur combiné | Exemple d'utilisation | Equivalence |
---|---|---|
&= | a &= 0b1111; | a = a & 0b1111; |
|= | a |= 0b1111; | a = a | 0b1111; |
^= | a ^= 0b1111; | a = a ^ 0b1111; |
<<= | a <<= 0b1111; | a = a << 0b1111; |
>>= | a >>= 0b1111; | a = a >> 0b1111; |
>>>= | a >>>= 0b1111; | a = a >>> 0b1111; |
Voici un petit exemple d'utilisation de ces opérateurs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class Demo { public static void main( String [] args ) { int value = 0b00010001; value <<= 2; // value = value << 2; System.out.println( "<<= - " + Integer.toBinaryString( value ) ); value = 0b00010001; value >>= 2; // value = value >> 2; System.out.println( ">>= - " + Integer.toBinaryString( value ) ); } } |
Améliorations / Corrections
Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.
Emplacement :
Description des améliorations :