JavaRush /Blog Java /Random-FR /Opérateurs logiques en Java

Opérateurs logiques en Java

Publié dans le groupe Random-FR
Opérations logiques en Java.  Opérations au niveau du bit en Java - 1

Opérations logiques en Java

Les opérations logiques sont effectuées à l'aide d'opérateurs booléens. Pardonnez la tautologie, mais c’est exactement ainsi que les choses se passent. Les opérations logiques de base (en programmation et en mathématiques) peuvent être appliquées à des arguments logiques (opérandes) et peuvent également être utilisées pour former des expressions plus complexes, similaires aux opérations arithmétiques sur les nombres. Par exemple l'expression :

(a | b) | (c < 100) & !(true) ^ (q == 5)
est une expression logique complexe avec quatre opérandes : (a | b), où аet bsont des variables de type boolean (c < 100) (true) (q == 5) . À son tour, une expression logique simple (a | b)se compose également de deux arguments d'opérande. Un opérande logique est une expression dont on peut dire qu'elle est vraie ou fausse, vraie ou fausse . Dans le langage Java, un opérande booléen est une expression de type booleanou booléen, par exemple :
  • (2 < 1)— opérande logique, sa valeur est fausse
  • true- un opérande logique dont la valeur est évidemment vraie
  • boolean a- peut aussi être un opérande logique, comme un booléen a
  • int a = 2- n'est pas un opérande logique , c'est juste une variable de typeint
  • String a = "true"n'est pas non plus un opérande logique . Il s'agit d'une chaîne dont la valeur de texte est "true".
Les opérations logiques suivantes sont disponibles en Java :
  • Négation logique , également connue NOTsous le nom d'inversion. En Java, il est indiqué par le !symbole « » devant l'opérande. S'applique à un opérande.
  • Logique et , c'est aussi ANDune conjonction. Indiqué par un &symbole « » entre les deux opérandes auxquels il est appliqué.
  • Logique ou en Java , c'est aussi - OR, c'est aussi disjonction. En Java, il est indiqué par le symbole «| » entre deux opérandes.
  • Disjonction exclusive ou stricte XOR. En Java, il est indiqué par le symbole «^ » entre deux opérandes.
  • En Java, les opérateurs logiques incluent le conditionnel ou , noté ||, ainsi que le conditionnel et - &&.
Remarque : également en logique mathématique, on considère la relation d'équivalence, c'est-à-dire l'égalité. Cependant, en Java, l'opérateur d'égalité==n'est pas considéré comme un opérateur logique. Attention! En Java, les opérateurs logiques&,|et^s'appliquent également aux entiers. Dans ce cas, ils fonctionnent légèrement différemment et sont appelés opérateurs logiques au niveau du bit (ou au niveau du bit). À leur sujet - vers la fin de l'article. Examinons un tableau avec une brève description de chacun des opérateurs logiques Java, et ci-dessous nous les décrirons plus en détail et fournirons des exemples de code.
Opérateur Java Nom Taper Brève description Exemple
! « non » logique (négation) Unaire !xsignifie « pas x ». Renvoie true si l'opérande est false . Renvoie false si l'opérande est true . boolean x = true;
Alors
// !x == false
& ET logique ( AND, multiplication) Binaire Renvoie vrai si les deux opérandes sont vrais . a = true;
b = false;
Alors
a & b == false
| OU logique ( OR, addition) Binaire Renvoie true si au moins un des opérandes est true . a = true;
b = false;
Alors
a | b == true
^ OU exclusif logique ( XOR) Binaire Renvoie true si un et un seul des opérandes est vrai . Renvoie false si les deux opérandes sont true ou false . Essentiellement, cela renvoie vrai si les opérandes sont différents. a = true;
b = false;
Alors
a ^ b == true
&& ET conditionnel (ET logique court) Binaire Identique à , &mais si l'opérande à gauche de &est false , cet opérateur renvoie false sans vérifier le deuxième opérande.
|| OU conditionnel (OU logique court) Binaire Identique à , |mais si l'opérateur de gauche est true , l'opérateur renvoie true sans vérifier le deuxième opérande.

Opérations logiques dans le cours JavaRush

Il n'y a pas d'échappatoire aux opérations logiques, et dans le cours JavaRush, elles apparaissent dès les premiers niveaux, avec les conditions et le type de données booléen. Les programmeurs apprennent progressivement à utiliser les méthodes de la logique mathématique. Pour des manipulations plus confiantes avec des constructions logiques, une certaine dextérité et une compréhension de certains processus sont nécessaires. Ces opérations sont donc abordées plus en détail et à un tout autre niveau à la fin de la quête Multithreading, lorsque la plupart des étudiants ne sont plus trop distraits directement par la syntaxe et les constructions, mais tentent d'approfondir l'essence de la tâche.

Opérations logiques en Java.  Opérations au niveau du bit en Java - 2

Opérateur de négation logique !

Cet opérateur est unaire, ce qui signifie qu'il s'applique à une seule expression ou opérande booléen. C'est très simple à comprendre, comme toute négation : l'opérateur change simplement le sens de l'expression en son contraire. Table de vérité ou résultats de l'exécution d'une opération de négation :
La valeur d' un !un
FAUX vrai
vrai FAUX
Exemple. Opération de négation logique
public class Solution {
   public static void main(String[] args) {
       boolean a = true;
       System.out.println(!a); // here our boolean expression reverses its value
       System.out.println(!false); // non-false expression, as you might guess, will be equal to... what?
       System.out.println(!(2 < 5)); // expression (2 < 5) is true, so its negation is false

   }
}
Le résultat du programme sera le suivant :

false
true
false

ET logique - &, ainsi que ET conditionnel - &&

Le ET logique ou la conjonction est appliqué à deux expressions, et son résultat ne sera vrai que si les deux opérandes sont vrais. Autrement dit, si l'un des opérandes aor best faux , alors l'expression a & bsera fausse quelle que soit la valeur du deuxième opérateur. Si vous imaginez que vrai est le nombre 1 et faux est 0, alors l'opérateur &fonctionne exactement de la même manière qu'une multiplication régulière. Par conséquent, le ET logique est souvent appelé « multiplication logique ». Et, en passant, ce fait permet de se souvenir rapidement du fonctionnement de l'opérateur &et de ne pas le confondre avec l'opérateur logique ou |. Table de vérité ET, c’est aussi le résultat du travail de l’opérateur&
un b un B
vrai vrai vrai
vrai FAUX FAUX
FAUX vrai FAUX
FAUX FAUX FAUX
ET logique, c'est aussi une conjonction, exemples :
public class Solution {
   public static void main(String[] args) {
       boolean a = true;
       boolean b = false;
       boolean c = true;
       System.out.println(a & b); // if we multiply true by false, we will definitely get false
       System.out.println(a & c); // true to true will be true
       System.out.println(false & (2 > 5));
 System.out.println((2 < 5) & false);
 // regardless of the truthfulness of the expression in brackets, in which case we have to be content with false
   }
}
Résultat du programme :

false
true
false
false
L'opérateur &&est parfois appelé « AND court ». Il produit le même résultat lorsque vous travaillez avec des opérandes logiques que l'opérateur &. Il y a cependant une différence dans son travail lui-même. Ainsi, vous avez déjà remarqué que si a & bl'opérande dans l'expression ( ) aest faux , alors cela n'a aucun sens de vérifier la valeur de l'opérande b: le résultat de l'opération sera définitivement faux . Donc si nous n’avons pas fondamentalement besoin de la valeur du deuxième opérande, en l’utilisant &&nous réduisons le nombre de calculs dans le programme. Si nous remplaçons tous les opérateurs de l'exemple &par &&, le résultat sera exactement le même, mais le programme lui-même fonctionnera un peu plus vite (même si nous ne le remarquerons pas, puisqu'il s'agit de mili-micro... en bref , très petites unités de temps).

Le OU logique est l'opérateur |, ainsi que le OU conditionnel est l'opérateur ||

L'opérateur OR en Java est représenté par le symbole |. Un OU logique ou une disjonction est appliqué à deux expressions, et son résultat sera faux si et seulement si les deux opérandes sont faux. Ici, nous observons dans une certaine mesure la même image que dans le cas de l'opérateur &, mais exactement le contraire. Autrement dit, si au moins un opérande est vrai , alors l'expression a | best garantie vraie quelle que soit la valeur du deuxième opérateur. Si &cela se comporte comme une multiplication logique, alors OU est une addition logique, si vous imaginez que vrai vaut 1 et faux vaut 0. N'oubliez pas que l'addition logique fonctionne différemment de l'addition normale. 1 + 1 dans ce cas n'est pas égal à 2, mais à 1 (le chiffre 2 n'existe tout simplement pas dans ce système). Parfois, la disjonction est comprise comme le maximum de 0 et 1, et dans ce cas, si au moins un opérande est égal à 1 ( true ), nous obtenons exactement true . Table de vérité OU, également appelée résultat de l'opérateur |:
un b un | b
vrai vrai vrai
vrai FAUX vrai
FAUX vrai vrai
FAUX FAUX FAUX
OU logique, également appelé disjonction, exemple :
public class Solution {
   public static void main(String[] args) {
       boolean a = true;
       boolean b = false;
       boolean c = true;
       System.out.println(!a | b); // Compose the use of two logical operators: a == true, so !a, as we already know, is false.
       System.out.println(a | c);
       System.out.println((2 < 5) | false); // expression (2 < 5) is true, which means that for any second operand we get a true result
       System.out.println((2 > 5) | true);

   }
}
Résultat:

false
true
true
true
Si nous utilisons l'opérateur conditionnel OR - ||au lieu de |, nous obtiendrons exactement le même résultat, mais, comme dans le cas du AND conditionnel &&, il agira de manière économique : si nous « rencontrons » le premier opérande égal à true , la valeur de le deuxième opérande n'est pas vérifié, mais immédiatement le résultat est vrai .

XOR Java - OU exclusif logique - opérateur ^

XOR, addition modulo 2, XOR logique, soustraction logique, disjonction stricte, complément au niveau du bit... l'opérateur ^a de nombreux noms en algèbre booléenne. Le résultat de l'application de cet opérateur à deux opérandes sera vrai si les opérandes sont différents et faux si les opérandes sont identiques. Par conséquent, il est pratique de le comparer en soustrayant des zéros ( false ) et des uns ( true ). Table de vérité XOR, également appelée résultat de l'opérateur^ :
Booléen un Booléen b un^b
vrai vrai FAUX
vrai FAUX vrai
FAUX vrai vrai
FAUX FAUX FAUX
Exemple:
public class Solution {
   public static void main(String[] args) {
       boolean a = true;
       boolean b = false;
       boolean c = true;
       System.out.println(!a ^ b); // Compose the use of two logical operators: a == true, so !a, as we already know, is false.
       System.out.println(a ^ c);
       System.out.println((2 < 5) ^ false);
       System.out.println((2 > 5) ^ true);
   }
}
Résultat:

false
false
true
true

Priorité des opérations logiques

Tout comme en mathématiques, en programmation, les opérateurs ont un ordre d’exécution spécifique lorsqu’ils apparaissent dans la même expression. Les opérateurs unaires ont des avantages par rapport aux opérateurs binaires et la multiplication (même logique) par rapport à l'addition. Nous avons classé les opérateurs logiques plus haut dans la liste, plus leur priorité est élevée :
  1. !
  2. &
  3. ^
  4. |
  5. &&
  6. ||
Regardons des exemples. La conjonction et la disjonction ( &et |) ont des priorités différentes :
public class Solution {
   public static void main(String[] args) {
       boolean a = true, b = true, c = false;
       System.out.println(a | b & c);
}
Si nous devions procéder de gauche à droite, c'est-à-dire appliquer d'abord l'opérateur |puis - &, nous obtiendrions la valeur false . Mais en fait, si vous exécutez ce programme, vous serez sûr que le résultat sera vrai , puisque l'opérateur logique AND &aura une priorité plus élevée que l'opérateur logique OR |. Pour éviter toute confusion, vous devez vous rappeler ce qui &se comporte comme une multiplication et |ce qui se comporte comme une addition. Vous pouvez modifier l'ordre de priorité. Utilisez simplement des parenthèses, comme en mathématiques à l’école. Modifions un peu notre exemple de code :
public class Solution {
   public static void main(String[] args) {
       boolean a = true, b = true, c = false;
       System.out.println((a|b)&c);
}
Quoi de neuf? Nous utilisons d’abord l’addition logique entre parenthèses, puis la multiplication. Le résultat sera faux .

Expressions logiques complexes

Bien entendu, nous pouvons combiner des expressions booléennes et des opérateurs. Rappelons l'expression du début de l'article :
(a | b) | (c < 100) & !(true) ^ (q == 5)
Maintenant, ça n'a plus l'air si effrayant. Écrivons un programme qui affiche sa valeur, après avoir préalablement déterminé les valeurs de a, b, сet q. Exemple de calcul de la valeur d'une expression booléenne complexe
public class Solution {
   public static void main(String[] args) {
       boolean a = true;
       boolean b = false;
       int c = 25;
       int q = 2;
       System.out.println((a|b) | (c < 100) & !(true)^(q == 5));
   }
}
Note:qnotre variable est de type int, mais q == 5c'est une expression booléenne, et elle est égale à false , puisque ci-dessus nous avons initialisé avec qle chiffre 2. Il en va de même avec la variable c. Ce nombre est égal à 25, mais (c < 100) est une expression booléenne égale à true . Le résultat de ce programme :

true
Les expressions booléennes complexes peuvent être utilisées pour tester des conditions très complexes et ramifiées, mais il ne faut pas en abuser : elles rendent le code difficile à lire.

Opérateurs au niveau du bit (bit au niveau du bit)

Au début de l'article, nous avons mentionné que les opérateurs &, |et ^peuvent être utilisés en relation avec les types entiers Java. Dans ce cas, ce sont des opérateurs au niveau du bit. On les appelle également au niveau du bit, car un chiffre équivaut à un bit et ces opérations fonctionnent spécifiquement avec des bits. Bien sûr, ils fonctionnent quelque peu différemment des opérateurs logiques, et pour comprendre exactement comment, vous devez savoir ce qu'est un système de nombres binaires. Si vous n'en savez rien ou si vous l'avez complètement oublié, nous vous suggérons de lire d'abord l'article Java : bits et octets , et de rappeler à tous que dans le système de nombres binaires, il n'y a que deux chiffres - 0 et 1, et toutes les données dans l'ordinateur est représenté avec précision en utilisant des zéros et des uns conditionnels. N'importe lequel des nombres auxquels nous sommes habitués (décimaux ; pour eux, il y a 10 chiffres différents de 0 à 9, avec lesquels nous écrivons n'importe quel nombre) peut être représenté dans le système de nombres binaires. Vous pouvez convertir un nombre décimal en binaire en utilisant la division séquentielle en colonne à l'aide de la base du système numérique (2). Les restes de la division à chaque étape, écrits dans l'ordre inverse, nous donneront le nombre binaire souhaité. Voici par exemple la conversion du nombre décimal 103 en représentation binaire : Opérations logiques en Java.  Opérations au niveau du bit en Java - 3

Système de nombres binaires dans le cours JavaRush

Dans le cours JavaRush, ils parlent du système de nombres binaires tout en étudiant la quête MultiThreading (niveau 10, cours 1) ; après le cours, il y a plusieurs tâches à consolider. Cependant, ce sujet n'est pas du tout difficile, et même si vous n'êtes pas encore allé aussi loin dans le cours, vous y arriverez probablement.

En plus de &, |et ^Java utilise également des opérateurs au niveau du bit :
  • ~ opérateur de négation au niveau du bit
  • >>décalage au niveau du bit vers la droite
  • >>>décalage à droite au niveau du bit non signé
  • <<décalage au niveau du bit vers la gauche
Pour les débutants, les opérateurs au niveau du bit semblent très déroutants et artificiels. Le plus souvent, ils ne comprennent pas à quoi ils servent, sauf pour résoudre des problèmes éducatifs. En fait, ils peuvent être utilisés au minimum pour organiser une division et une multiplication efficaces, et les professionnels les utilisent pour l'encodage/décodage, le cryptage et la génération de nombres aléatoires.

Opérateurs au niveau du bit &, | et ^

Regardons un exemple du fonctionnement de ces opérateurs. Disons que nous avons deux entiers :
int a = 25;
int b = 112; 
Nous devons leur appliquer trois opérations et &afficher le résultat à l’écran. Voici le code du programme : |^
public class Solution {
   public static void main(String[] args) {

       int a = 25;
       int b = 112;

       int res1 = a & b;
       int res2 = a | b;
       int res3 = a ^ b;

       System.out.println("a & b = " + res1);
       System.out.println("a | b = " + res2);
       System.out.println("a ^ b = " + res3);

   }
}
Le résultat du programme est le suivant :

a & b = 16
a | b = 121
a ^ b = 105
Si vous ne comprenez pas ce qui se passe, le résultat semble très, très mystérieux. En fait, tout est plus simple qu’il n’y paraît. Les opérateurs au niveau du bit « voient » les numéros d'opérandes sous leur forme binaire. Et puis ils appliquent des opérateurs logiques &, |ou ^aux chiffres (bits) correspondants des deux nombres. Ainsi, car &le dernier bit de la représentation binaire du nombre 25 s'additionne logiquement au dernier bit de la représentation binaire du nombre 112, l'avant-dernier bit avec l'avant-dernier, et ainsi de suite : Opérations logiques en Java.  Opérations au niveau du bit en Java - 4La même logique peut être tracée dans le cas de |et ^. Opérations logiques en Java.  Opérations au niveau du bit en Java - 5

Décalage de bits vers la gauche ou la droite

Il existe plusieurs opérateurs de décalage de bits en Java. Les opérateurs les plus couramment utilisés <<sont et >>. Ils déplacent la représentation binaire d’un nombre respectivement vers la gauche ou la droite, et dans le cas d’un déplacement vers la droite, tout en préservant le signe (nous expliquerons ci-dessous ce que signifie conserver le signe). Il existe un autre opérateur de décalage à droite >>>. Cela fait la même chose mais >>ne sauvegarde pas le signe. Examinons donc leur travail à l'aide d'un exemple. int a = 13 a << 1décale tous les bits de la représentation binaire du nombre a vers la gauche de 1 bit. Pour simplifier, imaginons le nombre 13 en binaire comme 0000 1101. En fait, ce nombre ressemble à ceci : 00000000 00000000 00000000 00001101, puisque Java intalloue 4 octets ou 32 bits pour les nombres. Cependant, cela ne joue aucun rôle dans l'exemple, donc dans cet exemple, nous considérerons que notre nombre est d'un octet. Opérations logiques en Java.  Opérations au niveau du bit en Java - 6Le bit libéré à droite est rempli de zéros. À la suite de cette opération, nous obtenons le nombre 26. a << 2Elle décale tous les bits de la représentation binaire du nombre avers la gauche de 2 bits, et les deux bits libérés à droite sont remplis de zéros. En conséquence, nous obtiendrons le nombre 52. a << 3Le résultat sera 104... Remarquez le modèle ? Le décalage au niveau du bit avers la gauche de n positions fonctionne comme multiplier un nombre apar 2 à la puissance n. La même chose s'applique aux nombres négatifs. Cela -13 << 3donnera le résultat -104. a >> ndécale la représentation binaire d’un nombre n positions vers la droite. Par exemple, 13 >> 1 transforme le nombre 1101 en nombre 0110, c'est-à-dire 6. Et 13 >> 2le résultat sera 3. Autrement dit, en substance, nous divisons ici le nombre par 2 à la puissance n, où n est le nombre de changements à droite, mais avec une mise en garde : si le nombre est impair, lors de cette opération on semble réinitialiser le dernier bit du nombre. Mais avec les négatifs, la situation est quelque peu différente. Disons, essayons de vérifier ce que le programme produira si vous lui demandez d'effectuer une opération -13 >> 1. Vous verrez le chiffre -7, et non -6, comme vous pourriez le penser. Cela est dû à la manière dont les nombres négatifs sont stockés dans Java et d’autres langages de programmation. Ils sont stockés dans ce qu'on appelle du code complémentaire. Dans ce cas, le chiffre le plus significatif (celui de gauche) est donné sous le signe. Dans le cas d’un nombre négatif, le chiffre le plus significatif est 1.

Code supplémentaire

Considérons le nombre int a = 13. Si dans le programme vous imprimez sa représentation binaire sur la console à l'aide de la commande System.out.println(Integer.toBinaryString(a));, alors nous obtiendrons 1101. En fait, il s'agit d'une notation abrégée, puisque le numéro de type intoccupe 4 octets en mémoire, donc l'ordinateur le « voit » davantage comme ça:

00000000 00000000 00000000 00001101
Le chiffre le plus significatif est zéro, ce qui signifie que nous avons un nombre positif. Pour convertir en code supplémentaire :
  1. Nous écrivons le nombre -13 dans ce qu'on appelle le « code direct ». Pour ce faire, remplacez le chiffre le plus significatif du nombre par 1.
    Résultat de l'action :

    
    10000000 0000000 0000000 00001101
  2. Ensuite, on inverse tous les bits (on change 0 en 1 et 1 en 0) sauf le bit de signe. En fait, nous l'avons déjà modifié.
    Résultat de l'action :

    
    11111111 11111111 11111111 11110010

    (oui, les étapes 1 et 2 pourraient être combinées, mais il vaut mieux y penser ainsi)

  3. Ajoutez 1 au nombre obtenu.
    Résultat de l'action :

    
    11111111 11111111 11111111 11110011
Le nombre binaire résultant est -13, écrit en code complément à deux, et le décalage de bits (et d'autres opérations) lui sera appliqué spécifiquement. C’est juste que la différence dans la logique de fonctionnement n’est pas perceptible dans toutes les opérations. Disons que pour un même déplacement vers la gauche, la différence est imperceptible ; on peut travailler avec des nombres négatifs de la même manière qu'avec des nombres positifs. Maintenant, passons à droite -13 >> 1. Puisque notre opérateur >>préserve le signe, dans cette opération tous les bits libérés à gauche sont remplis non pas de zéros, mais de uns. Ainsi, en déplaçant le nombre

11111111 11111111 11111111 11110011
un bit vers la droite, ce qui donne la séquence de bits suivante :

11111111 11111111 11111111 11111001
Si nous convertissons ce nombre en code direct (c'est-à-dire soustrayons d'abord 1, puis inversons tous les bits sauf le premier), nous obtenons le nombre :

10000000 00000000 00000000 00000111
ou -7. Maintenant que nous avons compris l'opérateur de décalage à droite préservant les signes, il deviendra clair en quoi il diffère de l'opérateur >>>. a >>> n— cette opération est un décalage non signé, c'est-à-dire qu'elle décale la représentation binaire d'un nombre avers la droite de n bits, mais remplit les n bits libérés à gauche non pas avec des uns, comme l'opérateur >>, mais avec des zéros. Faisons l'opération -13 >>> 1. Nous avons déjà le nombre -13en complément à deux :

11111111 11111111 11111111 11110011
En décalant vers la droite d'1 bit et en remplissant le bit libre par zéro, on obtient le nombre suivant :

01111111 11111111 11111111 11111001
Ce qui donne le nombre en notation décimale 2147483641.

Opérateur de négation au niveau du bit ~

Cet opérateur unaire fonctionne très simplement : il inverse chaque bit de la représentation binaire d'un entier. Prenons le numéro -13:

11111111 11111111 11111111 11110011
L'opération de négation au niveau du bit ~13inversera simplement la valeur de chaque bit. En conséquence nous obtenons :

00000000 00000000 00000000 00001100
Ou 12sous forme décimale.

Brèves conclusions

  • Tous les opérateurs logiques s'appliquent aux expressions booléennes, c'est-à-dire celles dont on peut dire qu'elles sont vraies ou fausses .
  • Si les opérateurs &, |ou ^sont appliqués à des nombres, on ne parle plus d'opérations logiques, mais d'opérations au niveau du bit. C'est-à-dire que les deux nombres sont convertis en système binaire et que les opérations d'addition logique, de multiplication ou de soustraction sont appliquées à ces nombres bit par bit.
  • En logique mathématique, les opérateurs &et |correspondent à la conjonction et à la disjonction.
  • Le ET logique revient à multiplier 1 ( vrai ) et 0 ( faux ).
  • Le OU logique revient à trouver le maximum entre 1 ( vrai ) et 0 ( faux ).
  • Pour la négation au niveau du bit d'un entier a, l'opérateur est utilisé ~a.
  • Pour nier logiquement une expression booléenne a, utilisez l'opérateur !a.
  • Les nombres négatifs sont stockés et traités dans le code complément à deux.
  • Un décalage au niveau du bit vers la droite peut >>ou non conserver le signe ( >>>).
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION