JavaRush /Blog Java /Random-FR /Opérations au niveau du bit en Java

Opérations au niveau du bit en Java

Publié dans le groupe Random-FR
Vous connaissez probablement le mot « battre ». Sinon, apprenons-le :) Un bit est l'unité minimale de mesure des informations dans un ordinateur. Son nom vient de l'anglais « binaire chiffre » - « nombre binaire ». Un bit peut être exprimé sous la forme de l'un des deux nombres suivants : 1 ou 0. Il existe un système numérique spécial basé sur des uns et des zéros - binaire. Nous n’entrerons pas dans la jungle des mathématiques et notons simplement que n’importe quel nombre en Java peut être converti sous sa forme binaire. Pour ce faire, vous devez utiliser des classes wrapper. Opérations au niveau du bit - 1Par exemple, voici comment procéder pour un nombre int:
public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(Integer.toBinaryString(x));
   }
}
Sortie de la console :

101010110
1010 10110 (j'ai ajouté un espace pour plus de lisibilité) est le nombre 342 en binaire. Nous avons en fait divisé ce nombre en bits individuels : des zéros et des uns. C'est avec eux que l'on peut effectuer des opérations dites bit à bit.
  • ~— opérateur « NON » au niveau du bit.

Cela fonctionne très simplement : il parcourt chaque bit de notre nombre et change sa valeur à l'opposé : des zéros en uns, des uns en zéros. Si on l'applique à notre nombre 342, voici ce que nous obtenons : 101010110 - le nombre 342 en binaire 010101001 - le résultat de l'expression ~342 Mais comme une variable int prend 4 octets, c'est à dire 32 bits, en fait, le nombre dans la variable est stocké comme : 00000000 00000000 00000001 01010110- le nombre 342 dans une variable de type int en java 11111111 11111111 11111110 10101001- le résultat de l'expression ~342 en java Essayons de faire cela en pratique :
public class Main {

   public static void main(String[] args) {

       int x = 342;
       System.out.println(Integer.toBinaryString(~x));
   }
}
Sortie de la console :
11111111111111111111111010101001
  • &— opérateur au niveau du bit « ET »

Comme vous pouvez le voir, son écriture est assez similaire au « ET » logique ( &&). L'opérateur &&, comme vous vous en souvenez, ne revient trueque si les deux opérandes sont vrais. Bitwise &fonctionne de la même manière : il compare deux nombres petit à petit. Le résultat de cette comparaison est le troisième nombre. Par exemple, prenons les nombres 277 et 432 : 100010101 - le nombre 277 sous forme binaire 110110000 - le nombre 432 sous forme binaire Ensuite, l'opérateur &compare le premier bit du nombre supérieur avec le premier bit du nombre inférieur. Puisqu'il s'agit d'un opérateur « ET », le résultat ne sera égal à 1 que si les deux bits sont égaux à 1. Dans tous les autres cas, le résultat sera 0. 100010101 & 110110000 _______________ 100010000 - résultat du travail & On compare d'abord les premiers bits de deux nombres entre eux, puis deuxièmes bits, troisièmes, etc. Comme vous pouvez le constater, dans deux cas seulement, les deux bits des nombres étaient égaux à 1 (le premier et le cinquième bits). Le résultat de toutes les autres comparaisons était 0. Par conséquent, nous avons finalement obtenu le nombre 100010000. Dans le système décimal, cela correspond au nombre 272. Vérifions :
public class Main {

   public static void main(String[] args) {
       System.out.println(277&432);
   }
}
Sortie de la console :

272
  • |- "OU" au niveau du bit. Le principe de fonctionnement est le même : on compare deux nombres petit à petit. Seulement maintenant, si au moins un des bits est égal à 1, le résultat sera égal à 1. Regardons les mêmes nombres - 277 et 432 :
100010101 | 110110000 _______________ 110110101 - le résultat du travail. | Ici, le résultat est différent : seuls les bits qui étaient des zéros dans les deux nombres sont restés des zéros. Le résultat du travail est le nombre 110110101. Dans le système décimal cela correspond au nombre 437. Vérifions :
public class Main {

   public static void main(String[] args) {
       System.out.println(277|432);
   }
}
Sortie de la console :

437
Nous avons tout compté correctement ! :)
  • ^- OU exclusif au niveau du bit (également connu sous le nom de XOR)
Nous n’avons jamais rencontré un tel opérateur auparavant. Mais cela n’a rien de compliqué. Cela ressemble à un « ou » ordinaire. La différence est une : le « ou » ordinaire renvoie truesi au moins un opérande est vrai. Mais pas nécessairement un – si les deux sont là true– alors le résultat true. Mais le « ou » exclusif ne revient trueque si l’un des opérandes est vrai. Si les deux opérandes sont vrais, un « ou » régulier renverra true(« au moins un est vrai »), mais un ou exclusif renverra false. C'est pourquoi on l'appelle exclusif. Connaissant le principe des opérations au niveau du bit précédentes, vous pouvez probablement facilement effectuer vous-même l'opération 277^432. Mais mieux vaut le découvrir ensemble encore une fois :) 100010101 ^ 110110000 _______________ 010100101 - le résultat du travail ^ Voici notre résultat. Les bits qui étaient identiques dans les deux nombres renvoyaient 0 (la formule « un de » ne fonctionnait pas). Mais ceux qui formaient une paire 0-1 ou 1-0 se sont finalement transformés en une unité. En conséquence, nous avons obtenu le nombre 010100101. Dans le système décimal, cela correspond au nombre 165. Voyons si nous avons calculé correctement :
public class Main {

   public static void main(String[] args) {
       System.out.println(277^432);
   }
}
Sortie de la console :

165
Super! Tout est exactement comme nous le pensions :) Il est maintenant temps de se familiariser avec les opérations appelées décalages de bits. Le nom, en principe, parle de lui-même. Nous allons prendre un nombre et déplacer ses bits vers la gauche et la droite :) Voyons à quoi cela ressemble :

Décaler vers la gauche

Le décalage des bits vers la gauche est indiqué par le signe << Exemple :
public class Main {

   public static void main(String[] args) {
       int x = 64;//meaning
       int y = 3;//quantity

       int z = (x << y);
       System.out.println(Integer.toBinaryString(x));
       System.out.println(Integer.toBinaryString(z));
   }
}
Dans cet exemple, le nombre x=64est appelé valeur. Ce sont ses morceaux que nous allons déplacer. On va décaler les bits vers la gauche (cela peut être déterminé par le sens du signe <<) Dans le système binaire, le nombre 64 = 1000000 Le nombre y=3est appelé quantité. Quantité répond à la question « de combien de bits vers la droite/gauche faut-il décaler les bits d'un nombre x? » Dans notre exemple, nous allons les décaler de 3 bits vers la gauche. Pour rendre le processus de changement plus clair, regardons l'image. Dans notre exemple, nous utilisons des nombres de type int. Intoccupent 32 bits de la mémoire de l'ordinateur. Voici à quoi ressemble notre numéro 64 d'origine : Opérations au niveau du bit - 2Et maintenant, au sens littéral du terme, nous prenons chacun de nos bits et le décalons vers la gauche de 3 cellules : Opérations au niveau du bit - 3Voilà ce que nous avons. Comme vous pouvez le voir, tous nos bits ont été décalés et 3 zéros supplémentaires ont été ajoutés en dehors de la plage. 3 - parce que nous décalions de 3. Si nous décalions de 10, 10 zéros seraient ajoutés. L’expression x << ysignifie donc « décaler les bits d’un nombre хy de cellules vers la gauche ». Le résultat de notre expression était le nombre 1000000000, qui dans le système décimal est égal à 512. Vérifions :
public class Main {

   public static void main(String[] args) {
       int x = 64;//meaning
       int y = 3;//quantity

       int z = (x << y);
       System.out.println(z);
   }
}
Sortie de la console :

512
C'est exact! En théorie, les bits peuvent être décalés indéfiniment. Mais puisque nous avons le numéro int, il n’y a que 32 cellules disponibles. Parmi ceux-ci, 7 sont déjà occupés par le numéro 64 (1 000 000). Par conséquent, si nous effectuons, par exemple, 27 déplacements vers la gauche, notre seule unité deviendra hors de portée et « écrasera ». Il ne restera que des zéros !
public class Main {

   public static void main(String[] args) {
       int x = 64;//meaning
       int y = 26;//quantity

       int z = (x << y);
       System.out.println(z);
   }
}
Sortie de la console :

0
Comme prévu, celui-ci a dépassé les cellules de 32 bits et a disparu. Nous avons obtenu un nombre de 32 bits composé uniquement de zéros. Opérations au niveau du bit - 4Naturellement, dans le système décimal, cela correspond à 0. Une règle simple pour mémoriser les décalages vers la gauche : à chaque décalage vers la gauche, le nombre est multiplié par 2. Par exemple, essayons de calculer le résultat de l'expression sans images avec bits 111111111 << 3 . pour multiplier par trois le nombre 111111111 par 2. Le résultat est 888888888. Écrivons le code et vérifions-le :
public class Main {

   public static void main(String[] args) {
       System.out.println(111111111 << 3);
   }
}
Sortie de la console :

888888888

Changements à droite

Ils sont signalés par le signe >>. Ils font la même chose, mais dans l’autre sens ! :) Ne réinventons pas la roue et essayons de faire cela avec le même nombre int 64.
public class Main {

   public static void main(String[] args) {
       int x = 64;//meaning
       int y = 2;//quantity

       int z = (x >> y);
       System.out.println(z);
   }
}
Opérations au niveau du bit - 5Opérations au niveau du bit - 6Suite au décalage de 2 vers la droite, les deux zéros extrêmes de notre nombre sont sortis de la plage et ont été effacés. Nous avons obtenu le nombre 10000, qui dans le système décimal correspond au nombre 16. Sortie sur la console :

16
Une règle simple pour mémoriser les décalages à droite : chaque décalage à droite se divise par deux, en éliminant tout reste. Par exemple, 35 >> 2 cela signifie que nous devons diviser 35 par 2 2 fois, en supprimant le reste 35/2 = 17(en supprimant le reste 1) 17:2 = 8(en supprimant le reste 1). Le total 35 >> 2doit être égal à 8. Vérifiez :
public class Main {

   public static void main(String[] args) {
       System.out.println(35 >> 2);
   }
}
Sortie de la console :

8

Priorité des opérations en Java

Lorsque vous écrivez ou lisez du code, vous rencontrerez souvent des expressions dans lesquelles plusieurs opérations sont effectuées simultanément. Il est très important de comprendre dans quel ordre ils seront exécutés, sinon le résultat pourrait être inattendu. Comme il existe de nombreuses opérations en Java, elles ont toutes été séparées dans une table spéciale :

Priorité des opérateurs

Les opérateurs Priorité
suffixe expr++ expr--
unaire ++expr --expr +expr ~ !
Multiplicatif * / %
additif + -
changement << >> >>>
relationnel < > <= >=exemple de
égalité == !=
ET au niveau du bit &
OU exclusif au niveau du bit ^
OU inclusif au niveau du bit |
ET logique &&
OU logique ||
ternaire ? :
affectation = += -= *= /= %= &= ^= |= <<= >>= >>>=
Toutes les opérations s'effectuent de gauche à droite, mais en tenant compte de leur priorité. Par exemple, si l'on écrit : int x = 6 - 4/2; d'abord l'opération de division (4/2) sera effectuée. Même si elle est en deuxième position, elle a une priorité plus élevée. Les parenthèses ou les crochets modifient la priorité au maximum. Vous vous en souvenez probablement de l'école. Par exemple, si vous les ajoutez à une expression : int x = (6 - 4)/2; la soustraction sera effectuée en premier, puisqu'elle est calculée entre parenthèses. L'opérateur logique a &&une priorité plutôt faible, comme le montre le tableau. Par conséquent, le plus souvent, il sera exécuté en dernier. Par exemple : boolean x = 6 - 4/2 > 3 && 12*12 <= 119; Cette expression serait exécutée comme ceci :
  • 4/2 = 2

    boolean x = 6 - 2 > 3 && 12*12 <= 119;
  • 12*12 = 144

    boolean x = 6 - 2 > 3 && 144 <= 119;
  • 6-2 = 4

    boolean x = 4 > 3 && 144 <= 119;
  • Ensuite, les opérateurs de comparaison seront exécutés :

    4 > 3 = true

    boolean x = true && 144 <= 119;
  • 144 <= 119 = false

    boolean x = true && false;
  • Et enfin, le dernier opérateur sera exécuté &&.

    boolean x = true && false;

    boolean x = false;

    L'opérateur d'addition ( +), par exemple, a une priorité plus élevée que l'opérateur de comparaison !=(« différent » );

    Donc dans l'expression :

    boolean x = 7 != 6+1;

    d'abord l'opération 6+1 sera effectuée, puis la vérification 7!=7 (faux), et à la fin le résultat sera affecté à falsela variable x. L'affectation a généralement la priorité la plus basse de toutes les opérations - regardez dans le tableau.

Phew! Notre conférence a été longue, mais vous l'avez fait ! Si vous ne comprenez pas entièrement certaines parties de ce cours et des conférences précédentes, ne vous inquiétez pas, nous aborderons ces sujets plus d'une fois dans le futur. Voici quelques liens utiles pour vous :
  • Opérateurs logiques - Conférence JavaRush sur les opérations logiques. Nous n’y reviendrons pas de sitôt, mais vous pouvez les lire dès maintenant, il n’y aura aucun mal.
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION