1. Décalage binaire à gauche

Java dispose également de 3 opérateurs de décalage bit à bit : Si vous en avez vraiment besoin, vous pouvez très simplement décaler tous les bits d'un nombre de plusieurs positions vers la gauche ou vers la droite.

Pour décaler les bits d'un nombre vers la gauche, vous avez besoin de l' opérateur de décalage à gauche au niveau du bit . C'est comme ça que c'est écrit :

a << b

aest le nombre dont les bits sont décalés, et best un nombre qui indique combien de fois décaler les bits du nombre avers la gauche. Lors de cette opération, les bits de poids faible ajoutés à droite sont des zéros.

Exemples:

Exemple Résultat
0b00000011 << 1
0b00000110
0b00000011 << 2
0b00001100
0b00000011 << 5
0b01100000
0b00000011 << 20
0b001100000000000000000000

Décaler un chiffre vers la gauche a le même effet que multiplier un nombre par 2.

Vous voulez multiplier un nombre par 16 ? 16 est égal à 2 4 . Donc tu décales le nombre de 4 chiffres vers la gauche


2. Décalage au niveau du bit vers la droite

Les bits peuvent également être décalés vers la droite. Pour ce faire, utilisez l' opérateur de décalage droit au niveau du bit . C'est comme ça que c'est écrit :

a >> b

aest le nombre dont les bits sont décalés, et best le nombre de fois pour décaler les bits du nombre avers la droite.

Exemples:

Exemple Résultat
0b11000011 >> 1
0b01100001
0b11000011 >> 2
0b00110000
0b11000011 >> 5
0b00000110
0b11000011 >> 20
0b00000000

Décaler un chiffre vers la droite a le même effet que diviser un nombre par 2.

Lors de cette opération, les bits de poids fort ajoutés à gauche sont des zéros, mais pas toujours !

Important!

Le bit le plus à gauche d'un nombre signé est appelé bit de signe : si le nombre est positif, il l'est 0; mais si le nombre est négatif, ce bit est 1.

Lors du décalage des bits d'un nombre vers la droite, la valeur du bit de signe se décalerait normalement également et le signe du nombre serait perdu. En conséquence, pour les nombres négatifs (où le bit le plus à gauche est 1), ce bit reçoit un traitement spécial. Lors du décalage des bits d'un nombre vers la droite, a 0est ajouté à gauche si le bit le plus à gauche était 0, et a 1est ajouté à gauche si le bit le plus à gauche était 1.

Mais dans l'exemple ci-dessus, cela ne semble pas être le résultat. Pourquoi? Parce que les littéraux entiers sont ints, et  signifient en fait . C'est-à-dire que le bit le plus à gauche est zéro.0b111111110b00000000000000000000000011111111

De nombreux programmeurs sont frustrés par ce comportement de décalage vers la droite et préféreraient que le nombre soit toujours rempli de zéros. Java a donc ajouté un autre opérateur de décalage à droite .

C'est comme ça que c'est écrit :

a >>> b

a est le nombre dont les bits sont décalés, et b  est le nombre de fois pour décaler les bits du nombre avers la droite. Cet opérateur ajoute toujours des zéros à gauche, quelle que soit la valeur d'origine du bit de signe du nombre a.



3. Travailler avec des drapeaux

Les programmeurs ont créé un domaine d'étude presque entièrement nouveau sur la base d'opérations bit à bit et de décalage : travailler avec des drapeaux.

Lorsque les ordinateurs avaient très peu de mémoire, il était très populaire de regrouper beaucoup d'informations en un seul numéro. Un nombre était traité comme un tableau de bits : un int correspond à 32 bits et un long à 64 bits.

Vous pouvez écrire beaucoup d'informations dans un tel nombre, surtout si vous avez besoin de stocker des valeurs logiques ( trueou false). Un single longest comme un booleantableau composé de 64 éléments. Ces bits étaient appelés flags et étaient manipulés à l'aide des opérations suivantes :

  • définir le drapeau
    (faire un bit spécifique égal à 1)
  • drapeau de réinitialisation
    (faire un bit spécifique égal à 0)
  • vérifier le drapeau
    (vérifier la valeur d'un bit spécifique)

Et voici comment cela se passe avec les opérateurs au niveau du bit.

Pose d'un drapeau

Pour définir un bit spécifique sur 1, vous devez effectuer une opération OU au niveau du bit entre le nombre dont vous souhaitez définir le bit et un nombre spécialement créé, où seul ce bit est 1.

Par exemple, supposons que vous ayez le nombre 0b00001010et que vous deviez définir le 5ème bit sur 1. Dans ce cas, vous devez :

0b00001010 | 0b00010000 = 0b00011010

Si le 5e bit avait déjà été défini sur un, rien n'aurait changé.

En général, l'opération de positionnement d'un drapeau peut être écrite comme suit

a | (1 << b)

a est le nombre dont le bit sera défini sur 1. Et b est la position du bit à régler. L'utilisation de l'opérateur de décalage à gauche est très pratique ici, car vous pouvez immédiatement dire avec quel bit nous travaillons.

Réinitialiser un drapeau

Pour réinitialiser un bit spécifique (c'est-à-dire le régler sur 0) sans perturber les autres bits, vous devez effectuer une &opération entre le nombre dont vous souhaitez réinitialiser le bit (c'est-à-dire le régler sur 0) et un nombre spécialement créé, où tous les bits sont égaux à 1sauf pour le bit que vous souhaitez réinitialiser.

Par exemple, supposons que vous ayez le nombre 0b00001010et que vous deviez définir le 4ème bit sur 0. Dans ce cas, vous devez :

0b00001010 & 0b11110111 = 0b00000010

Si le 4ème bit avait déjà été mis à zéro, alors rien n'aurait changé.

De manière générale, l'opération de remise à zéro d'un drapeau peut s'écrire comme suit

a & ~(1 << b)

a est le nombre dont le bit sera réinitialisé à 0. Et b c'est la position du bit à effacer.

Pour obtenir un nombre où tous les bits sont 1sauf celui que nous voulons être zéro, nous décalons d'abord 1 b  positions vers la gauche, puis utilisons l' NOTopérateur au niveau du bit pour inverser le résultat.

Vérification d'un drapeau

En plus de définir ou de réinitialiser un indicateur spécifique, il vous suffit parfois de vérifier si un indicateur donné est défini, c'est-à-dire si un certain bit est égal à 1. C'est assez facile à faire avec un bitwise &.

Par exemple, supposons que vous deviez vérifier si le 4e bit est défini sur 1dans le nombre 0b00001010. Ensuite, vous devez faire ceci :

if ( (0b00001010 & 0b00001000) == 0b00001000 )

En général, l'opération de vérification d'un drapeau peut s'écrire comme suit

(a & (1 << b)) == (1 << b)

a est le nombre dont le bit est vérifié. Et b est la position du bit à vérifier.


4. Cryptage

L' XORopération au niveau du bit est souvent utilisée par les programmeurs pour un chiffrement simple. En général, un tel cryptage ressemble à ceci :

result = number ^ password;

number se trouvent les données que nous voulons crypter, password est un numéro spécial utilisé comme "mot de passe" pour les données, et result est le numéro crypté.

number == (number ^ password) ^ password;

L'important ici est que lorsque l' XORopérateur est appliqué deux fois à un numéro, il produit le numéro d'origine, quel que soit le "mot de passe".

Pour récupérer number du encrypted result, il vous suffit de refaire l'opération :

original number = result ^ password;

Exemple:

class Solution
{
   public static int[] encrypt(int[] data, int password)
   {
     int[] result = new int[data.length];
     for (int i = 0; i <  data.length; i++)
       result[i] = data[i] ^ password;
     return result;
   }

   public static void main(String[] args)
   {
     int[] data =  {1, 3, 5, 7, 9, 11};
     int password = 199;

     // Encrypt the array of data
     int[] encrypted = encrypt(data, password);
     System.out.println(Arrays.toString(encrypted));

     // Decrypt the array of data
     int[] decrypted = encrypt(encrypted, password);
     System.out.println(Arrays.toString(decrypted));
   }
}