Chapitre 1114 minDébutant
La logique en informatique : conditions, SQL, masques et bits
Par Josselyn C., prof de BTS SIO. Mis à jour le .
À la fin de ce chapitre, tu sauras
- simplifier une condition de programme avec les lois de Boole ;
- éviter les pièges de priorité et de NULL dans une clause WHERE ;
- utiliser les opérateurs bit à bit et les masques ;
- calculer une adresse de réseau par un ET logique.
5 exercices corrigés1 schéma
L'algèbre de Boole est partout dans le travail d'un informaticien : dans les conditions if et while d'un programme, dans les clauses WHERE d'une requête SQL, dans le calcul d'une adresse réseau (un ET logique bit à bit entre l'adresse IP et le masque) et dans les droits d'accès codés sur des bits. Ce chapitre fait le lien entre le cours de mathématiques et ces usages, avec des exemples en Python, en SQL et en réseau que tu retrouveras en SLAM comme en SISR.
Les opérateurs logiques des langages
| Opération | Python | C#, Java, JavaScript | PHP | SQL |
|---|---|---|---|---|
| Non | not a | !a | !$a | NOT a |
| Et | a and b | a && b | $a && $b | a AND b |
| Ou | a or b | a || b | $a || $b | a OR b |
| Ou exclusif (booléens) | a != b | a ^ b (C#, Java) ; a !== b (JavaScript) | $a xor $b | a XOR b (MySQL) |
Ces langages suivent tous la priorité du chapitre 1 : non, puis et, puis ou.
L'évaluation paresseuse (court-circuit). Les opérateurs and/&& et or/|| évaluent leur opérande de gauche d'abord, et ne calculent celui de droite que si c'est nécessaire. C'est l'application directe de deux règles de Boole : 0 · b = 0 (si la gauche d'un ET est fausse, le résultat est faux) et 1 + b = 1 (si la gauche d'un OU est vraie, le résultat est vrai). On s'en sert pour protéger un test :
# Si utilisateur vaut None, la partie droite n'est jamais évaluée : pas d'erreur.
if utilisateur is not None and utilisateur.actif:
ouvrir_session(utilisateur)
L'ordre des deux conditions compte : inversées, elles provoqueraient une erreur quand utilisateur vaut None. Le ET logique est commutatif ; son évaluation dans un programme ne l'est pas.
Simplifier une condition avec De Morgan
Les conditions écrites « au fil de la pensée » sont souvent plus compliquées qu'il ne faut. Les lois de l'algèbre de Boole les rendent lisibles.
# Avant : une négation de toute la condition, difficile à lire
if not (age >= 18 and inscrit):
refuser()
# Après De Morgan : non(a et b) = non a ou non b
if age < 18 or not inscrit:
refuser()
Une boucle de recherche s'arrête quand on a trouvé ou qu'on est arrivé au bout. Elle continue donc tant que non(trouvé ou fin), c'est-à-dire tant que non trouvé et non fin :
i, trouve = 0, False
while not trouve and i < len(tickets): # ≡ not (trouve or i >= len(tickets))
if tickets[i]["statut"] == "urgent":
trouve = True
else:
i += 1
D'autres simplifications fréquentes :
| Condition écrite | Condition simplifiée | Règle |
|---|---|---|
if ok == True: | if ok: | a = 1 équivaut à a |
if not (x != 0): | if x == 0: | Double négation |
if a or (not a and b): | if a or b: | a + a̅b = a + b |
if (a and b) or (a and not b): | if a: | ab + ab̅ = a |
if a and (a or b): | if a: | Absorption |
Conditions SQL : AND, OR, NOT et NULL
Dans une clause WHERE, la priorité NOT > AND > OR crée le piège classique déjà vu : WHERE statut = 'ouvert' OR statut = 'en cours' AND priorite = 'haute' se lit statut = 'ouvert' OR (statut = 'en cours' AND priorite = 'haute'). Mets toujours des parenthèses autour d'un OR combiné à un AND.
Les lois de De Morgan servent aussi en SQL : « les postes qui ne sont ni des portables ni des tablettes » s'écrit indifféremment
SELECT * FROM poste WHERE NOT (type_poste = 'portable' OR type_poste = 'tablette');
SELECT * FROM poste WHERE type_poste <> 'portable' AND type_poste <> 'tablette';
SELECT * FROM poste WHERE type_poste NOT IN ('portable', 'tablette');
SQL ajoute une troisième valeur de vérité, inconnu (UNKNOWN), produite par toute comparaison avec NULL. Un WHERE ne garde que les lignes où la condition est vraie : les lignes « inconnues » disparaissent, ce qui surprend souvent. NOT (inconnu) reste inconnu, vrai OR inconnu est vrai, faux AND inconnu est faux. Cette logique à trois valeurs et le piège de NOT IN avec un NULL sont détaillés dans le cours SQL : NULL et la logique à trois valeurs.
Les opérateurs bit à bit
Les opérateurs bit à bit appliquent une opération booléenne à chaque rang de bits de deux entiers, indépendamment des autres rangs.
| Opérateur | Python, C#, Java, JavaScript, PHP | Exemple sur 12 = 1100 et 10 = 1010 |
|---|---|---|
| ET bit à bit | a & b | 1100 & 1010 = 1000 = 8 |
| OU bit à bit | a | b | 1100 | 1010 = 1110 = 14 |
| OU exclusif bit à bit | a ^ b | 1100 ^ 1010 = 0110 = 6 |
| Complément bit à bit | ~a | inverse tous les bits |
| Décalage à gauche | a << n | multiplie par 2ⁿ : 5 << 1 = 10 |
| Décalage à droite | a >> n | divise par 2ⁿ (quotient entier) |
Les usages des opérateurs bit à bit reposent sur trois règles de Boole, appliquées à chaque bit :
- x · 0 = 0 et x · 1 = x : un ET avec un masque garde les bits où le masque vaut 1 et éteint les autres ;
- x + 1 = 1 et x + 0 = x : un OU avec un masque allume les bits où le masque vaut 1 ;
- x ⊕ 1 = x̅ et x ⊕ 0 = x : un XOR avec un masque inverse les bits où le masque vaut 1.
Le masque de sous-réseau : un ET logique
Une adresse IPv4 compte 32 bits. Le masque de sous-réseau a ses premiers bits à 1 (la partie réseau) et les suivants à 0 (la partie hôte). L'adresse du réseau s'obtient par un ET bit à bit entre l'adresse IP et le masque : les bits de la partie réseau sont gardés, ceux de la partie hôte sont mis à 0.
Exemple : 192.168.10.37/27. Le préfixe /27 donne un masque de 27 bits à 1 : 255.255.255.224. Les trois premiers octets du masque valent 255 (tout est gardé) ; le travail se fait sur le dernier octet.
| Dernier octet en binaire | Décimal | |
|---|---|---|
| Adresse IP | 0010 0101 | 37 |
| Masque | 1110 0000 | 224 |
| IP ET masque | 0010 0000 | 32 |
| IP OU (non masque) | 0011 1111 | 63 |
- Adresse du réseau : IP ET masque = 192.168.10.32.
- Adresse de diffusion (broadcast) : IP OU (complément du masque), tous les bits d'hôte à 1 = 192.168.10.63.
- Adresses utilisables : de 192.168.10.33 à 192.168.10.62, soit 2⁵ − 2 = 30 hôtes (5 bits d'hôte).
Deux machines sont dans le même réseau si et seulement si (IP₁ ET masque) = (IP₂ ET masque). C'est exactement le test que fait un poste avant d'envoyer un paquet : même réseau, envoi direct ; sinon, envoi à la passerelle.
import ipaddress
reseau = ipaddress.ip_interface("192.168.10.37/27").network
print(reseau, reseau.broadcast_address) # 192.168.10.32/27 192.168.10.63
# Le même calcul à la main, avec le ET bit à bit
ip = int(ipaddress.ip_address("192.168.10.37"))
masque = int(ipaddress.ip_address("255.255.255.224"))
print(ipaddress.ip_address(ip & masque)) # 192.168.10.32
Le découpage en sous-réseaux est traité en détail dans le cours réseaux, et l'écriture d'une adresse ou d'un masque en binaire dans le cours d'arithmétique.
Les droits Unix : des bits et des masques
Sous Linux, les droits d'un fichier sont trois groupes de trois bits : lecture (r = 4), écriture (w = 2), exécution (x = 1), pour le propriétaire, le groupe et les autres. chmod 754 signifie 111 101 100 : rwx pour le propriétaire, r-x pour le groupe, r-- pour les autres.
- Tester un droit : un ET avec le bit voulu. Le groupe a-t-il l'écriture ? Le chiffre du groupe est 5 = 101, et 101 ET 010 = 000 : non.
- Le umask retire des droits par défaut. Un fichier est créé avec les droits 666 ET (non umask). Avec le umask 022 : 666 ET (non 022) = 644 (
rw-r--r--). Pour un dossier, 777 ET (non 022) = 755.
Les droits Linux sont détaillés dans le cours administration Linux.
Les drapeaux : plusieurs booléens dans un entier
Une application peut ranger plusieurs droits dans un seul entier, chaque droit occupant un bit : LIRE = 1 (0001), ÉCRIRE = 2 (0010), SUPPRIMER = 4 (0100), ADMINISTRER = 8 (1000). On parle de drapeaux (flags) ou de masque de bits.
LIRE, ECRIRE, SUPPRIMER, ADMIN = 1, 2, 4, 8
droits = LIRE | ECRIRE # 0011 : on allume deux bits (OU)
droits |= SUPPRIMER # 0111 : on ajoute un droit (OU)
droits &= ~ECRIRE # 0101 : on retire un droit (ET avec le complément)
print(droits) # 5
print(droits & SUPPRIMER != 0, droits & ECRIRE != 0) # True False : on teste (ET)
C'est la technique des permissions Unix, des options de nombreuses fonctions système et des colonnes SET de MySQL.
Exercices
Exercice 1 sur 5 Calculer une adresse de réseau Réussi À revoir
Un poste a l'adresse 172.16.45.200 avec le masque 255.255.240.0 (/20).
- Écris en binaire le troisième octet de l'adresse et celui du masque.
- Calcule l'adresse du réseau par un ET bit à bit.
- Calcule l'adresse de diffusion.
Voir la réponseMasquer la réponse de l'exercice 1
- 45 = 0010 1101 ; 240 = 1111 0000.
- 0010 1101 ET 1111 0000 = 0010 0000 = 32. Le quatrième octet du masque vaut 0, donc le quatrième octet du réseau vaut 0. Réseau : 172.16.32.0/20.
- Les bits d'hôte (les 4 derniers bits du troisième octet et tout le quatrième) passent à 1 : 0010 1111 = 47 et 255. Diffusion : 172.16.47.255.
Tu avais trouvé ?
Exercice 2 sur 5 Même réseau ? Réussi À revoir
Trois postes ont le masque 255.255.255.192 (/26) : A = 10.1.5.130, B = 10.1.5.190, C = 10.1.5.200. Lesquels sont dans le même réseau ?
Voir la réponseMasquer la réponse de l'exercice 2
192 = 1100 0000 : seuls les deux premiers bits du dernier octet comptent.
- A : 130 = 1000 0010, ET 1100 0000 = 1000 0000 = 128 → réseau 10.1.5.128.
- B : 190 = 1011 1110, ET 1100 0000 = 1000 0000 = 128 → réseau 10.1.5.128.
- C : 200 = 1100 1000, ET 1100 0000 = 1100 0000 = 192 → réseau 10.1.5.192.
A et B sont dans le même réseau ; C est dans un autre et devra passer par un routeur pour les joindre.
Tu avais trouvé ?
Exercice 3 sur 5 Réécrire une condition Réussi À revoir
Réécris chaque condition Python sans not devant une parenthèse, puis simplifie si possible.
not (connecte and admin)not (stock == 0 or archive)admin or (not admin and proprietaire)(a and b) or (a and not b) or (not a and b)
Voir la réponseMasquer la réponse de l'exercice 3
not connecte or not admin(De Morgan).stock != 0 and not archive(De Morgan, et la négation de==est!=).admin or proprietaire(a + a̅b = a + b).- (ab + ab̅) + a̅b = a + a̅b = a + b :
a or b.
Tu avais trouvé ?
Exercice 4 sur 5 Les droits d'un fichier Réussi À revoir
- Que signifie
chmod 640? Écris les droits en binaire et en lettres. - Quels droits ont les fichiers créés avec le umask 027 ? Et les dossiers ?
Voir la réponseMasquer la réponse de l'exercice 4
- 6 = 110, 4 = 100, 0 = 000 :
rw-r-----. Le propriétaire lit et écrit, le groupe lit, les autres n'ont aucun droit. - Fichiers : 666 ET (non 027). Chiffre par chiffre : 6 ET (non 0) = 6 ; 6 ET (non 2) = 110 ET 101 = 100 = 4 ; 6 ET (non 7) = 0. Résultat 640 (
rw-r-----). Dossiers : 777 ET (non 027) = 750 (rwxr-x---).
Tu avais trouvé ?
Exercice 5 sur 5 Une requête qui oublie ses parenthèses Réussi À revoir
Un technicien veut les tickets de priorité haute qui sont ouverts ou en attente. Il écrit :
SELECT * FROM ticket WHERE priorite = 'haute' AND statut = 'ouvert' OR statut = 'en attente';
- Écris la condition avec P : « priorité haute », O : « statut ouvert », A : « statut en attente », telle que SQL la comprend.
- Quels tickets en trop la requête renvoie-t-elle ? Corrige-la.
Voir la réponseMasquer la réponse de l'exercice 5
ANDpasse avantOR: SQL comprend (P ∧ O) ∨ A.- Elle renvoie aussi les tickets en attente de priorité basse ou normale (la partie A seule). La condition voulue est P ∧ (O ∨ A) :
SELECT * FROM ticket WHERE priorite = 'haute' AND (statut = 'ouvert' OR statut = 'en attente');
ou, plus lisible : WHERE priorite = 'haute' AND statut IN ('ouvert', 'en attente').
Tu avais trouvé ?