0Mode d'emploi
Comment travailler
- Lis dans l'ordre. Les sections 1 à 5 couvrent la séance du 21 septembre, les sections 6 à 8 celle du 28.
- Garde une feuille à côté. Pose chaque calcul à la main avant de regarder le mien ou d'utiliser un laboratoire.
- Réponds aux questions « Vérifie-toi » avant de cliquer. Une erreur ici ne coûte rien.
- Vérifie toujours en décimal. Un calcul binaire se contrôle en vingt secondes en repassant en base 10. C'est ton test unitaire.
- Rythme conseillé : sections 1 à 4 à une première séance, 5 à 7 à une deuxième (la 7 est la plus importante), puis 8 et 9.
Où ça se place dans le semestre
D'après le plan de ta prof, le 5 octobre est consacré aux portes logiques, et le 19 octobre tu construiras dans Logisim un additionneur capable de soustraire. Cet additionneur calcule exactement comme dans la section 7 de cette page : les deux cours vont ensemble. Les portes logiques ont leur propre page : Les portes logiques, depuis le tout début.
Les mots, et où ils sont expliqués
- •Bit, octet, mot
- •Combien de bits faut-il ?
- •Bases 2, 8, 10 et 16
- •Les conversions
- •Addition et soustraction
- •Taille fixe, retenue sortante
- •Signe et valeur absolue
- •Complément à un
- •Complément à deux
- •Calculer avec des signés
- •Retenue ou débordement ?
- •Caractères et nombres à virgule
- •Relecture de tes notes
1Le bit, l'octet, le mot
1.1 Le bit
Un processeur contient des milliards de minuscules interrupteurs électroniques, les transistors. Chacun est dans un état parmi deux. Tes notes le disent ainsi : 0, le courant ne passe pas ; 1, le courant passe. En réalité, on mesure plutôt une tension : basse pour 0, haute pour 1. L'idée reste la même : deux états, faciles à distinguer.
Un chiffre qui ne peut valoir que 0 ou 1 s'appelle un bit (binary digit, chiffre binaire). C'est la plus petite quantité d'information possible : la réponse à une question par oui ou par non.
Pourquoi deux états, et pas dix ?
Distinguer dix niveaux de tension serait fragile : avec un peu de bruit électrique, un 6 deviendrait un 7. Avec deux niveaux très éloignés, l'erreur est presque impossible. C'est le principe d'un interrupteur de lumière : il n'a pas de position « à moitié allumé ».
1.2 Octet et mot
| Nom | Taille | Exemple, usage |
|---|---|---|
| bit (bit) | 1 bit | 0 ou 1 |
| quartet (nibble) | 4 bits | 1011 ; exactement un chiffre hexadécimal (section 3.4) |
| octet (byte) | 8 bits | 1010 0111 ; la plus petite case de la mémoire qui a sa propre adresse |
| mot (word) | 16, 32 ou 64 bits selon la machine | la taille des nombres que le processeur traite en une seule opération |
Ton i5-1135G7 est un processeur 64 bits : ses registres de calcul contiennent des mots de 64 bits. En français, un octet fait toujours 8 bits, alors que la taille d'un mot dépend de la machine. C'est pourquoi on précise toujours le nombre de bits.
Attention aux outils x86 (débogueurs, désassembleurs) : par tradition, WORD y désigne 16 bits, DWORD 32 bits et QWORD 64 bits, quel que soit le processeur.
On écrit les bits par paquets de 4 pour les lire plus facilement, comme on écrit 65 536 avec une espace : 1010 0111 plutôt que 10100111.
1.3 Combien de valeurs avec n bits ?
Avec 1 bit, on écrit 2 valeurs : 0 et 1. Avec 2 bits, 4 valeurs : 00, 01, 10, 11. Chaque bit ajouté double le nombre de possibilités : on reprend toutes les combinaisons précédentes, une fois avec un 0 devant, une fois avec un 1 devant.
À retenir
Avec n bits, on peut écrire 2n combinaisons différentes. Utilisées pour des entiers positifs, elles vont de 0 à 2n − 1.
Pourquoi « − 1 » ? Parce qu'on commence à 0. Avec 3 chiffres décimaux, il y a 10³ = 1 000 combinaisons, de 000 à 999 : la plus grande vaut 1 000 − 1. Pour l'octet, 2⁸ = 256 combinaisons, de 0 à 255 : c'est le « de 0 à 255 » de tes notes.
| n bits | 2n valeurs | entiers de 0 à | où on le rencontre |
|---|---|---|---|
| 1 | 2 | 1 | vrai ou faux |
| 4 | 16 | 15 | un chiffre hexadécimal |
| 8 | 256 | 255 | un octet ; une composante de couleur en CSS |
| 10 | 1 024 | 1 023 | 2¹⁰ = 1 024 ≈ 1 000 : d'où le préfixe « kibi » (Ki) |
| 16 | 65 536 | 65 535 | un numéro de port TCP ou UDP |
| 32 | 4 294 967 296 | 4 294 967 295 | une adresse IPv4 |
| 64 | ≈ 1,8 × 10¹⁹ | ≈ 1,8 × 10¹⁹ | un registre de ton processeur |
Les puissances de 2 de ton cours sont à connaître par cœur, au moins jusqu'à 2¹⁰ : 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1 024.
La question inverse : combien de bits faut-il ?
Elle revient sans cesse en TD. Pour représenter N valeurs différentes, il faut le plus petit n tel que 2n ≥ N.
- Numéroter les 30 étudiants d'un groupe : 2⁴ = 16 ne suffit pas, 2⁵ = 32 suffit. Il faut 5 bits (numéros 0 à 29).
- Écrire tous les entiers de 0 à 200 : cela fait 201 valeurs. 2⁷ = 128 ne suffit pas, 2⁸ = 256 suffit. Il faut 8 bits.
- Distinguer 1 000 valeurs : 2¹⁰ = 1 024, donc 10 bits.
Le piège du « + 1 »
Pour écrire les entiers de 0 à N, il y a N + 1 valeurs. Pour aller jusqu'à 256 inclus, 8 bits ne suffisent pas : 256 s'écrit 1 0000 0000, avec 9 bits.
ko ou Kio ?
Un Kio (kibioctet) vaut 1 024 octets, un ko (kilooctet) vaut 1 000 octets. Les fabricants de disques comptent en puissances de 10, beaucoup de logiciels en puissances de 2. C'est pourquoi un SSD de 512 Go s'affiche autour de 477 Gio : 512 × 10⁹ / 2³⁰ ≈ 476,8.
1.4 Laboratoire : l'octet
Clique sur les bits pour les allumer ou les éteindre. Chaque bit allumé ajoute son poids, écrit au-dessus. Essaie d'écrire 167, puis 255, puis 128.
Vérifie-toi (section 1)
Combien de valeurs différentes peut-on écrire avec 6 bits ?
Combien de bits faut-il au minimum pour numéroter 100 objets ?
Quel est le plus grand entier qu'on peut écrire sur 16 bits, en non signé ?
Un mot de 32 bits, c'est combien d'octets ?
2La numération positionnelle
2.1 Ce que veut dire « 2026 »
Tu as écrit cet exemple dans tes notes. On le reprend, parce que tout le reste en découle.
Chaque chiffre est multiplié par une puissance de 10 qui dépend de sa position. On numérote les positions à partir de la droite, en commençant à 0, comme les indices d'une liste en Python. Le même chiffre 2 vaut 2 000 en position 3, et 20 en position 1. C'est pour ça qu'on parle de numération positionnelle (positional notation). Les chiffres romains, eux, ne sont pas positionnels : dans XXX, chaque X vaut dix, quelle que soit sa place.
2.2 Changer de base
Le nombre 10 n'a rien de spécial : il vient de nos dix doigts. On peut remplacer 10 par n'importe quel entier b ≥ 2, qu'on appelle la base.
Numération en base b
On utilise b chiffres, de 0 à b − 1. Le chiffre placé en position k vaut chiffre × bk, et la valeur du nombre est la somme de ces produits :
(cn−1 … c1 c0)b = cn−1 × bn−1 + … + c1 × b + c0
C'est la formule encadrée dans tes notes : « chiffre × baseposition ».
| Base | Nom | Chiffres | Poids des positions |
|---|---|---|---|
| 2 | binaire | 0 1 | 1, 2, 4, 8, 16, 32… |
| 8 | octal | 0 1 2 3 4 5 6 7 | 1, 8, 64, 512… |
| 10 | décimal | 0 1 … 9 | 1, 10, 100, 1 000… |
| 16 | hexadécimal | 0 … 9 A B C D E F | 1, 16, 256, 4 096… |
En base 16, il faut seize chiffres, et nos chiffres s'arrêtent à 9. On emprunte donc des lettres : A = 10, B = 11, C = 12, D = 13, E = 14, F = 15. Chacune est un seul chiffre : dans (1A)₁₆, le A vaut 10 unités, et le nombre vaut 1 × 16 + 10 = 26.
On écrit la base en indice : (1010)₂ = (10)₁₀. Sans indice, « 10 » est ambigu : dix en décimal, deux en binaire, huit en octal, seize en hexadécimal.
Dans tes outils de tous les jours
- En Python, les préfixes
0b,0oet0xindiquent la base :0b1010 == 10. Les fonctionsbin(167),oct(167),hex(167)convertissent, etint('5D7', 16)fait l'inverse. Sers-t'en pour vérifier tes calculs, jamais pour les faire à ta place. - En CSS, dans ton cours de site personnel, une couleur
#FF8800est trois octets écrits en hexadécimal : rouge FF = 255, vert 88 = 136, bleu 00 = 0.
2.3 Compter : le compteur kilométrique
Un compteur kilométrique a des roues numérotées de 0 à 9. Quand une roue passe de 9 à 0, elle fait avancer d'un cran la roue de gauche : c'est la retenue (carry). En base b, c'est pareil, mais chaque roue n'a que b chiffres. En binaire, une roue n'a que 0 et 1 : dès qu'elle dépasse 1, elle repasse à 0 et pousse sa voisine. C'est pourquoi 0111 + 1 = 1000 : trois roues repassent à 0 d'un coup, exactement comme 999 + 1 = 1 000.
Ton tableau de 0 à 21 se lit avec cette image. La colonne de droite alterne 0, 1, 0, 1. La suivante change tous les 2 nombres, la suivante tous les 4, puis tous les 8. Chaque colonne change deux fois moins souvent que sa voisine de droite.
2.4 Pourquoi l'octal et l'hexadécimal ?
Le binaire est long à écrire et facile à mal recopier : 1 495 s'écrit 101 1101 0111. L'octal et l'hexadécimal servent d'abréviations, parce que 8 = 2³ et 16 = 2⁴. Un chiffre octal remplace exactement 3 bits, et un chiffre hexadécimal exactement 4 bits (section 3.4). Un octet s'écrit donc toujours avec 2 chiffres hexadécimaux, de 00 à FF.
C'est pour ça que les adresses mémoire s'écrivent en hexadécimal, comme tu l'as noté. Dans un débogueur, ou sur Root-Me, tu verras des adresses comme 0x7ffd3a2c1e40.
Vérifie-toi (section 2)
Que vaut (25)₉ en décimal ?
Que vaut (10)₁₆ en décimal ?
Quel est le plus grand chiffre en base 8 ?
Dans (1000)₂, combien vaut le 1 ?
3Les conversions
3.1 D'une base b vers la base 10
On applique la définition : chaque chiffre, multiplié par la base puissance sa position, puis on additionne.
La méthode du programmeur (Horner)
On lit les chiffres de gauche à droite, et on fait à chaque fois : valeur = valeur × base + chiffre. Pour (1011011)₂ : 1, puis 1 × 2 + 0 = 2, puis 2 × 2 + 1 = 5, puis 11, 22, 45, 91. Pas besoin de connaître les puissances, et c'est exactement ce que fait int('1011011', 2) :
def vers_decimal(chiffres, base):
valeur = 0
for c in chiffres:
valeur = valeur * base + int(c, 16)
return valeur
3.2 De la base 10 vers une base b : les divisions successives
On divise le nombre par b et on note le reste. On recommence avec le quotient, jusqu'à obtenir un quotient nul. Le résultat s'écrit avec les restes, lus du dernier au premier. Voici ton exemple de 72 en binaire :
| division | quotient | reste |
|---|---|---|
| 72 ÷ 2 | 36 | 0 |
| 36 ÷ 2 | 18 | 0 |
| 18 ÷ 2 | 9 | 0 |
| 9 ÷ 2 | 4 | 1 |
| 4 ÷ 2 | 2 | 0 |
| 2 ÷ 2 | 1 | 0 |
| 1 ÷ 2 | 0 | 1 |
On lit la colonne des restes de bas en haut : (72)₁₀ = (1001000)₂, soit 0100 1000 sur 8 bits. Vérification : 64 + 8 = 72.
Pourquoi lire à l'envers ? Fais la même chose en base 10 avec 2026 : 2026 ÷ 10 = 202, reste 6. Le reste, c'est le chiffre le plus à droite, et diviser par 10 décale le nombre d'un cran vers la droite. En base 2, c'est pareil : le premier reste, 72 mod 2, est le chiffre des unités (position 0). Les restes sortent donc de droite à gauche, et il faut les relire dans l'autre sens. En Python :
def vers_base(n, b):
chiffres = ""
while n > 0:
chiffres = "0123456789ABCDEF"[n % b] + chiffres # on ajoute à GAUCHE
n = n // b
return chiffres or "0"
La méthode marche pour toutes les bases. Ton exemple en base 8 : 167 ÷ 8 = 20 reste 7 ; 20 ÷ 8 = 2 reste 4 ; 2 ÷ 8 = 0 reste 2. Donc (167)₁₀ = (247)₈.
3.3 Méthode 2 : retirer les puissances
Imagine que tu dois payer 167 € avec des billets de 128, 64, 32, 16, 8, 4, 2 et 1 €, chaque billet au plus une fois. Tu prends le plus gros billet possible, puis le suivant, et ainsi de suite. C'est ce que tu as fait pour 167 :
Les billets pris donnent les 1 : (167)₁₀ = 1010 0111. Cette méthode est la plus rapide quand tu connais tes puissances de 2. Pour les bases 8 et 16, les divisions sont plus sûres.
3.4 Binaire, octal, hexadécimal : les paquets
La méthode des paquets
Binaire vers octal : on coupe le nombre en paquets de 3 bits en partant de la droite, on complète le dernier paquet à gauche avec des zéros, et on remplace chaque paquet par son chiffre (de 0 à 7).
Binaire vers hexadécimal : pareil, avec des paquets de 4 bits.
Dans l'autre sens, on remplace chaque chiffre par son paquet de 3 ou 4 bits.
Ton exemple, 1 495 = 10111010111. Les zéros ajoutés à gauche sont en gris.
paquets de 3 bits → (2727)₈
paquets de 4 bits → (5D7)₁₆
Pourquoi ça marche ? Un paquet de 3 bits vaut de 0 à 7, exactement un chiffre octal. Et les paquets successifs, en partant de la droite, pèsent 2⁰, 2³, 2⁶, c'est-à-dire 1, 8, 64 : les puissances de 8. Le découpage ne change pas le nombre, il le relit seulement par blocs.
Toujours couper depuis la droite
Si tu coupes 10111010111 depuis la gauche (101 110 101 11), tu obtiens n'importe quoi. C'est la position 0, les unités, qui doit tomber dans le premier paquet.
Le tableau à connaître par cœur, avec les 16 paquets de 4 bits. Les 8 premiers donnent aussi les paquets de 3 bits de l'octal (on enlève le 0 de tête).
| hexa | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| décimal | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| binaire | 0000 | 0001 | 0010 | 0011 | 0100 | 0101 | 0110 | 0111 | 1000 | 1001 | 1010 | 1011 | 1100 | 1101 | 1110 | 1111 |
Ton deuxième exemple, 267 = 1 0000 1011 : en paquets de 3, 100 001 011 donne (413)₈ ; en paquets de 4, 0001 0000 1011 donne (10B)₁₆.
3.5 Entre octal et hexadécimal : le binaire sert de pont
8 et 16 ne sont pas des puissances l'une de l'autre, il n'y a donc pas de raccourci direct. On passe par le binaire, comme dans tes notes avec (ACDC)₁₆ :
3.6 Laboratoire : le convertisseur
Tape un nombre et choisis sa base. La page affiche ses quatre écritures, les paquets de bits, et les divisions successives vers la base de ton choix. Fais toujours la conversion à la main d'abord.
Vérifie-toi (section 3)
Que vaut (1101)₂ en décimal ?
Comment s'écrit (7F)₁₆ en binaire ?
Comment s'écrit (101110)₂ en octal ?
Pour convertir 1 000 en binaire par divisions, le premier reste obtenu est…
4Additionner et soustraire, dans n'importe quelle base
4.1 L'addition binaire
On pose l'addition en colonnes, comme à l'école, en partant de la droite. Il n'y a que quatre cas à connaître :
| calcul | résultat | j'écris | je retiens |
|---|---|---|---|
| 0 + 0 | 0 | 0 | 0 |
| 0 + 1 ou 1 + 0 | 1 | 1 | 0 |
| 1 + 1 | 10 | 0 | 1 |
| 1 + 1 + 1 (avec une retenue) | 11 | 1 | 1 |
« 1 + 1 = 10 » se lit « un plus un égale deux », écrit en binaire : j'écris 0, je retiens 1. Les deux additions de tes notes, avec leurs retenues en rouge :
| 1 | 1 | 1 | 1 | retenues | ||
| 1 | 0 | 1 | 1 | 11 | ||
| + | 0 | 1 | 1 | 1 | 7 | |
| 1 | 0 | 0 | 1 | 0 | 18 |
| 1 | 1 | 1 | retenues | |||||||
| 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 14 | ||
| + | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 15 | |
| 0 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 29 |
4.2 La même règle dans toutes les bases
Addition en base b
Dans chaque colonne, on additionne les deux chiffres et la retenue éventuelle. Si la somme est plus petite que b, on l'écrit. Sinon, on écrit somme − b et on retient 1.
C'est la phrase de tes notes : « si on dépasse, on écrit de combien on dépasse, et on retient 1 ».
Ton addition en octal, colonne par colonne en partant de la droite (les sommes de chaque colonne sont faites en décimal, de tête) : 2 + 4 = 6 ; 7 + 3 = 10, qui dépasse 8, donc j'écris 10 − 8 = 2 et je retiens 1 ; 6 + 3 + 1 = 10, j'écris 2, je retiens 1 ; 5 + 6 + 1 = 12, j'écris 4, je retiens 1 ; 2 + 2 + 1 = 5 ; 1 + 1 = 2.
| 1 | 1 | 1 | retenues | |||||
| 1 | 2 | 5 | 6 | 7 | 2 | (ABBA)₁₆ = 43 962 | ||
| + | 1 | 2 | 6 | 3 | 3 | 4 | (ACDC)₁₆ = 44 252 | |
| 2 | 5 | 4 | 2 | 2 | 6 | 88 214 |
Ton addition en hexadécimal : A + C = 10 + 12 = 22, j'écris 22 − 16 = 6, je retiens 1 ; B + D + 1 = 11 + 13 + 1 = 25, j'écris 9 ; B + C + 1 = 24, j'écris 8 ; A + A + 1 = 21, j'écris 5, et la dernière retenue donne un chiffre de plus.
| 1 | 1 | 1 | 1 | retenues | ||
| A | B | B | A | 43 962 | ||
| + | A | C | D | C | 44 252 | |
| 1 | 5 | 8 | 9 | 6 | 88 214 |
4.3 La soustraction : l'emprunt
Quand le chiffre du haut est trop petit, on emprunte 1 à la colonne de gauche. Ce 1 vaut une base entière dans la colonne actuelle : 10 en décimal, 2 en binaire, 8 en octal, 16 en hexadécimal. C'est ta note : « on ajoute 16 à celui qui emprunte, on retire 1 à sa voisine ».
Soustraction en base b
Si le chiffre du haut est plus petit que celui du bas, on lui ajoute b, et on retire 1 au chiffre du haut de la colonne de gauche.
Si cette colonne de gauche contient 0, elle emprunte à son tour à sa propre voisine, et le 0 traversé devient b − 1 : 9 en décimal, 1 en binaire, 7 en octal, F en hexadécimal. C'est le piège de 100 − 1 = 99.
C'est la soustraction qu'on a faite ensemble. Les « −1 » marquent les colonnes qui ont prêté 1 à leur voisine de droite. À la position 3, on emprunte à travers la position 4, qui vaut 0 et devient 1 :
| −1 | −1 | −1 | emprunts | |||||
| 1 | 0 | 1 | 0 | 1 | 1 | 43 | ||
| − | 0 | 0 | 1 | 1 | 0 | 1 | 13 | |
| 0 | 1 | 1 | 1 | 1 | 0 | 30 |
Ton exemple en hexadécimal : 9 − A est impossible, donc 9 + 16 = 25 et 25 − 10 = 15 = F ; le E a prêté, il devient D, et D − 8 = 5 ; enfin 1 − 0 = 1.
| −1 | emprunts | ||||
| 1 | E | 9 | 489 | ||
| − | 0 | 8 | A | 138 | |
| 1 | 5 | F | 351 |
4.4 Laboratoire : poser une opération
Choisis une base et une opération, tape deux nombres, et suis le calcul colonne par colonne avec le bouton « Colonne suivante ».
Vérifie-toi (section 4)
(111)₂ + (1)₂ = ?
En hexadécimal, 9 + 8 = ?
En binaire, 1000 − 1 = ?
5Taille fixe : ce que fait vraiment la machine
Sur papier, quand une addition dépasse, on ajoute un chiffre à gauche. Une machine ne peut pas : un registre de 8 bits a 8 cases, pas une de plus. Le bit qui devrait sortir à gauche est perdu pour le résultat. On l'appelle la retenue sortante (carry out).
| 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | retenues | ||
| 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 255 | ||
| + | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | |
| 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 : la retenue est sortie |
Sur 8 bits, 255 + 1 donne 0. Le compteur kilométrique fait pareil : après 999 999 km, il affiche 000 000.
Entiers non signés (unsigned) sur n bits
Ils vont de 0 à 2n − 1. Quand une addition produit une retenue sortante, le résultat affiché est faux : le vrai résultat ne tient pas sur n bits. Le processeur range ce bit dans un indicateur (flag) appelé C, pour carry.
Autrement dit, sur n bits, la machine calcule modulo 2n : elle ne garde que le reste de la division par 2n. 255 + 1 = 256, et 256 modulo 256 = 0. Retiens bien cette idée : c'est elle qui va permettre de représenter les nombres négatifs.
En Python, les entiers n'ont pas de taille fixe : 255 + 1 donne 256. Mais en C, en Java, ou avec NumPy, les entiers ont une taille fixe et ce phénomène arrive vraiment (section 7.6).
6Les nombres négatifs
6.1 Le problème
En mémoire, il n'y a pas de signe « − » : il n'y a que des bits. Il faut donc une convention, une règle fixée à l'avance qui dit quelles suites de bits représentent des nombres négatifs. Tes notes en contiennent trois, présentées dans un ordre logique : chacune corrige un défaut de la précédente.
Le principe le plus important de cette page
Une suite de bits ne veut rien dire toute seule. 1001 0110 vaut 150, −22, −105 ou −106 selon la convention avec laquelle on la lit. Ce n'est pas la mémoire qui décide, c'est le programme, à travers le type de la variable.
C'est comme la date 03/04 : le 3 avril en France, le 4 mars aux États-Unis. Les chiffres sont les mêmes, la convention de lecture change tout.
6.2 Signe et valeur absolue
C'est la première idée de tes notes (page 5) : on réserve le bit de gauche, appelé bit de poids fort (most significant bit), au signe. 0 pour +, 1 pour −. Les 7 autres bits donnent la valeur absolue (sign-magnitude).
| nombre | signe | valeur absolue sur 7 bits | sur 8 bits |
|---|---|---|---|
| +5 | 0 | 000 0101 | 0000 0101 |
| −5 | 1 | 000 0101 | 1000 0101 |
| −1 | 1 | 000 0001 | 1000 0001 |
Sur 8 bits, on va de −127 à +127. C'est simple à lire, mais il y a deux défauts graves.
- Deux zéros : 0000 0000 (+0) et 1000 0000 (−0, dans tes notes). Pour tester si un nombre est nul, il faudrait vérifier deux motifs.
- L'addition ordinaire ne marche plus. Avec l'additionneur de la section 4, 1 + (−1) donne −2 :
| 1 | retenues | |||||||||
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | +1 | ||
| + | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | −1 en signe et valeur absolue | |
| 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | −2 : faux |
Il faudrait un circuit spécial qui compare les signes, puis additionne ou soustrait les valeurs absolues. C'est faisable, mais lourd.
6.3 Complément à un
Deuxième idée, avec ta définition : « je prends la valeur positive et je l'inverse ». Pour obtenir −x, on inverse chaque bit de x : les 0 deviennent 1 et les 1 deviennent 0 (ones' complement).
Inverser n'est pas retourner
Page 6 de tes notes, tu as écrit −7 = 1110 0000 en complément à un. C'est 0000 0111 lu dans un miroir : tu as retourné l'ordre des bits. Inverser, c'est changer chaque bit sans le déplacer. Tu l'as d'ailleurs corrigé un peu plus bas, avec −7 = 1111 1000.
Le bit de gauche indique toujours le signe, et on va encore de −127 à +127. Il reste deux zéros : 0000 0000 et 1111 1111 (le « −0 = 1111 1111 » de tes notes).
L'addition marche presque, à une correction près, la retenue circulaire (end-around carry) : si une retenue sort à gauche, on ne la jette pas, on la rajoute au résultat. Exemple, 5 + (−3) :
| 1 | 1 | 1 | 1 | 1 | 1 | retenues | ||||
| 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 5 | ||
| + | 1 | 1 | 1 | 1 | 1 | 1 | 0 | 0 | −3 en complément à un | |
| 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | une retenue sort : on la garde |
| 1 | retenues | |||||||||
| 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | résultat sans la retenue | ||
| + | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | + la retenue circulaire | |
| 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 2 : juste |
Pourquoi ce + 1 ? Inverser 8 bits, c'est calculer 255 − x : on soustrait x de 1111 1111, colonne par colonne, sans jamais d'emprunt. Donc en complément à un, −3 est codé par 255 − 3. Quand la somme dépasse 255, la retenue qui sort fait perdre 256, soit 1 de trop par rapport aux 255 utilisés. On rend ce 1 en l'ajoutant.
C'est l'exemple sur 16 bits en bas de la page 8 de tes notes : 3 292 + (−1 406) = 1 886.
| 1 | 1 | 1 | 1 | 1 | 1 | retenues | ||||||||||||
| 0 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 1 | 1 | 0 | 0 | 3 292 | ||
| + | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | −1 406 en complément à un | |
| 1 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | 1 | une retenue sort |
| 1 | retenues | |||||||||||||||||
| 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 1 | 0 | 1 | résultat sans la retenue | ||
| + | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | + la retenue circulaire, une fois | |
| 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 1 | 1 | 1 | 1 | 0 | 1 886 |
Une seule retenue circulaire
La retenue circulaire s'ajoute une seule fois. Dans tes notes, tu as ajouté 1 une deuxième fois, dans le cadre du bas, et obtenu 0000 0111 0101 1111. Ce deuxième + 1 est en trop : le résultat est 0000 0111 0101 1110 = 1 886.
Restent deux défauts : deux zéros, et une addition qui demande parfois un deuxième passage dans l'additionneur.
6.4 Complément à deux
C'est la convention de tous les processeurs actuels, le tien compris. Pour obtenir −x, on inverse tous les bits, puis on ajoute 1 (two's complement). C'est la ligne de tes notes : « complément à 1, et je rajoute 1 à la fin ».
| x | x en binaire | inversé | + 1 = −x |
|---|---|---|---|
| 1 | 0000 0001 | 1111 1110 | 1111 1111 |
| 7 | 0000 0111 | 1111 1000 | 1111 1001 |
| 32 | 0010 0000 | 1101 1111 | 1110 0000 |
| 58 | 0011 1010 | 1100 0101 | 1100 0110 |
| 100 | 0110 0100 | 1001 1011 | 1001 1100 |
| 127 | 0111 1111 | 1000 0000 | 1000 0001 |
Les lignes 32 et 58 sont dans tes notes, et elles sont justes.
- Un seul zéro. Comme dans tes notes : on inverse 0000 0000, on obtient 1111 1111, on ajoute 1 et on obtient 1 0000 0000. Sur 8 bits, le 1 de gauche tombe : −0 = 0.
- De −128 à +127 sur 8 bits. En général, de −2n−1 à 2n−1 − 1 sur n bits. Il y a un négatif de plus que de positifs, parce que 0 occupe une place du côté où le bit de gauche vaut 0.
- −128 = 1000 0000 est un cas spécial : son opposé est lui-même (inverser donne 0111 1111, + 1 redonne 1000 0000). Sur 8 bits, +128 n'existe pas.
Pourquoi « inverser puis ajouter 1 » donne l'opposé
Reviens à la section 5 : sur 8 bits, la machine calcule modulo 256. Ajouter 256 ne change rien, puisque ce 256 est une retenue qui tombe à gauche. Pour la machine, −7 et 256 − 7 = 249 sont donc le même nombre. On représente −7 par le motif de 249 : 1111 1001.
| 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | retenues | ||
| 0 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 7 | ||
| + | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 249, c'est-à-dire −7 | |
| 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 (la retenue tombe) |
Ajouté à 7, ce motif donne 0 : il se comporte exactement comme −7. Et « inverser puis + 1 » calcule justement 256 − x : inverser donne 255 − x (section 6.3), et ajouter 1 donne 256 − x.
L'image de l'horloge
Sur une horloge de 12 heures, reculer de 3 heures ou avancer de 9 heures mène à la même heure : pour l'horloge, −3 et +9 sont le même déplacement. Sur 8 bits, l'horloge a 256 positions, et −7 se confond avec +249. Le laboratoire de la section 7.4 dessine cette horloge pour 4 bits.
Lire un nombre négatif
- Méthode 1 : refaire « inverser + 1 ». L'opération est son propre inverse, puisque l'opposé de l'opposé est le nombre de départ. Pour 1100 0110 : inversé 0011 1001, + 1 donne 0011 1010 = 58. Donc 1100 0110 = −58.
- Méthode 2 : le bit de gauche pèse −128. En complément à deux, les poids sont −128, 64, 32, 16, 8, 4, 2, 1. Ainsi 1111 1001 = −128 + 64 + 32 + 16 + 8 + 1 = −7. C'est la méthode la plus rapide, et elle explique pourquoi le bit de gauche donne le signe : les 7 autres bits valent au plus 127, ce qui ne compense jamais −128.
Astuce de calcul
Pour obtenir −x plus vite : en partant de la droite, recopie les bits jusqu'au premier 1 inclus, puis inverse tous les autres. Pour 58 = 0011 1010, on recopie « 10 », on inverse « 001110 » en « 110001 », et on obtient 1100 0110.
6.5 Les trois conventions côte à côte, sur 4 bits
Les lignes grisées commencent par un 1 : ce sont celles que chaque convention lit comme négatives, ou comme −0 (sauf en non signé, bien sûr).
| bits | non signé | signe et valeur absolue | complément à un | complément à deux |
|---|---|---|---|---|
| 0000 | 0 | 0 | 0 | 0 |
| 0001 | 1 | 1 | 1 | 1 |
| 0010 | 2 | 2 | 2 | 2 |
| 0011 | 3 | 3 | 3 | 3 |
| 0100 | 4 | 4 | 4 | 4 |
| 0101 | 5 | 5 | 5 | 5 |
| 0110 | 6 | 6 | 6 | 6 |
| 0111 | 7 | 7 | 7 | 7 |
| 1000 | 8 | −0 | −7 | −8 |
| 1001 | 9 | −1 | −6 | −7 |
| 1010 | 10 | −2 | −5 | −6 |
| 1011 | 11 | −3 | −4 | −5 |
| 1100 | 12 | −4 | −3 | −4 |
| 1101 | 13 | −5 | −2 | −3 |
| 1110 | 14 | −6 | −1 | −2 |
| 1111 | 15 | −7 | −0 | −1 |
Regarde la dernière colonne : de 0000 à 0111, on compte de 0 à 7 ; puis à 1000, on saute à −8 et on remonte jusqu'à −1. Les négatifs sont les grands nombres non signés, décalés de 16 : 1001 vaut 9 en non signé et 9 − 16 = −7 en complément à deux.
6.6 Laboratoire : une même suite de bits, plusieurs lectures
C'est un savoir-faire demandé par ta prof : interpréter une même suite de bits selon différentes conventions. Clique sur les bits et compare les lectures.
6.7 Passer de 8 à 16 bits : l'extension de signe
Pour écrire un nombre signé sur plus de bits, on recopie le bit de signe à gauche (sign extension) :
Compléter un négatif avec des zéros changerait sa valeur : 0000 0000 1111 1001 vaut 249. Avec des 1, c'est juste : sur 16 bits, −7 se code par 65 536 − 7 = 65 529, qui s'écrit bien 1111 1111 1111 1001.
Vérifie-toi (section 6)
En complément à deux sur 8 bits, quel est l'opposé de 0001 0100 (20) ?
Que vaut 1111 1111 en complément à deux ?
Sur 8 bits en complément à deux, la plage est…
Combien de zéros différents y a-t-il en complément à un ?
Pour passer −3 (1111 1101) de 8 à 16 bits, on écrit…
7Additionner et soustraire des nombres signés
7.1 La bonne nouvelle
En complément à deux, on additionne exactement comme en non signé, avec le même circuit, et on ignore la retenue qui sort à gauche. Sur 8 bits, elle vaut 256, et l'enlever ne change rien au calcul modulo 256 (section 6.4).
Et la soustraction n'a pas besoin de circuit à elle : A − B se calcule comme A + (−B). C'est la raison pour laquelle tous les processeurs utilisent le complément à deux : un seul additionneur fait les additions et les soustractions, sur les nombres signés comme non signés. Ta note sur l'UAL, « addition seulement », vient de là (on la précise en section 9).
7.2 La méthode, en six étapes
Calculer A + B ou A − B en complément à deux sur n bits
- Fixe la taille n (8 bits, sauf indication contraire), et vérifie que A et B tiennent dans la plage, de −128 à 127 sur 8 bits.
- Code chaque nombre. Un positif s'écrit en binaire, complété à gauche par des 0. Un négatif : on code sa valeur absolue, on inverse, on ajoute 1.
- Si c'est une soustraction, remplace − B par + (−B), en prenant le complément à deux de B.
- Additionne colonne par colonne, et ignore la retenue qui sort à gauche.
- Contrôle le débordement : si A et (±B) ont le même signe et que le résultat a le signe opposé, il est faux (section 7.4). Cas particulier : −(−128) n'existe pas sur 8 bits, donc soustraire −128 déborde dès que A est positif ou nul.
- Lis le résultat (si le bit de gauche vaut 1, il est négatif : section 6.4) et vérifie en décimal.
Règle d'or de l'étape 2 : on ne prend l'opposé que des nombres précédés d'un signe −. Dans 32 + (−58), seul 58 est négatif.
7.3 Cinq exemples détaillés
Exemple 1 : 32 + (−58), l'exemple de tes notes
| 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 32 | ||
| + | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | −58 | |
| 1 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | −26 |
Le bit de gauche vaut 1 : le résultat est négatif. On refait « inverser + 1 » : 0001 1001 + 1 = 0001 1010 = 26. Le résultat est −26, et 32 − 58 = −26.
Ce qui s'est passé dans tes notes
Tu as posé 1110 0000 + 1100 0110, c'est-à-dire (−32) + (−58). Ton addition est juste (elle donne −90, voir l'exemple 3), mais ce n'était pas le calcul demandé : dans 32 + (−58), le 32 est positif. Plus bas, pour 58 + (−32), tu as de nouveau pris −58 au lieu de 58.
Exemple 2 : 58 + (−32), avec une retenue qui sort
| 1 | 1 | 1 | retenues | |||||||
| 0 | 0 | 1 | 1 | 1 | 0 | 1 | 0 | 58 | ||
| + | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | −32 | |
| 1 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 26 (retenue ignorée) |
Une retenue sort à gauche. En complément à deux, ce n'est pas une erreur : on l'ignore, et le résultat 0001 1010 = 26 est juste.
Exemple 3 : (−32) + (−58), le calcul que tu as fait
| 1 | 1 | retenues | ||||||||
| 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | −32 | ||
| + | 1 | 1 | 0 | 0 | 0 | 1 | 1 | 0 | −58 | |
| 1 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | −90 (retenue ignorée) |
Lecture : −128 + 32 + 4 + 2 = −90. Deux négatifs donnent un négatif : tout va bien.
Exemple 4 : une soustraction, 45 − 100
| 1 | 1 | 1 | 1 | retenues | ||||||
| 0 | 0 | 1 | 0 | 1 | 1 | 0 | 1 | 45 | ||
| + | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | −100 | |
| 1 | 1 | 0 | 0 | 1 | 0 | 0 | 1 | −55 |
Lecture : −128 + 64 + 8 + 1 = −55. Et 45 − 100 = −55.
Exemple 5 : soustraire un négatif, −20 − (−50)
| 1 | 1 | 1 | retenues | |||||||
| 1 | 1 | 1 | 0 | 1 | 1 | 0 | 0 | −20 | ||
| + | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 50 | |
| 1 | 0 | 0 | 0 | 1 | 1 | 1 | 1 | 0 | 30 (retenue ignorée) |
Retenue ignorée, résultat 0001 1110 = 30.
7.4 Retenue ou débordement ?
Ta prof demande de distinguer ces deux phénomènes, que presque tout le monde confond au début.
| Retenue (carry), indicateur C | Débordement (overflow), indicateur V | |
|---|---|---|
| Ce que c'est | le bit qui sort à gauche de l'addition | le vrai résultat signé sort de la plage (−128 à 127 sur 8 bits) |
| Qui est concerné | les entiers non signés | les entiers signés en complément à deux |
| Comment le repérer | une retenue sort de la colonne de gauche | deux nombres de même signe donnent un résultat de signe opposé |
| Ce qu'il signifie | en addition, le résultat non signé est faux | le résultat signé est faux |
Ce sens de C vaut pour l'addition. Après une soustraction faite comme A + (−B), la retenue change de sens : sur les processeurs ARM, C = 1 veut dire « pas d'emprunt », et les processeurs x86 l'inversent. Pour une soustraction, retiens surtout V.
La règle du débordement
Il y a débordement quand on additionne deux nombres de même signe et qu'on obtient un résultat de l'autre signe : positif + positif = négatif, ou négatif + négatif = positif.
Si les deux nombres sont de signes opposés, le débordement est impossible : le résultat est entre les deux, donc il tient forcément.
Le circuit utilise une règle équivalente : il y a débordement quand la retenue qui entre dans la colonne de gauche est différente de celle qui en sort. « Différent », c'est la porte XOR de la page sur les portes logiques.
Les quatre cas possibles, sur 8 bits. Chaque addition est lue deux fois : en non signé et en signé.
C = 0, V = 0 : 5 + 3
| 1 | 1 | 1 | retenues | |||||||
| 0 | 0 | 0 | 0 | 0 | 1 | 0 | 1 | 5 | ||
| + | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 | 3 | |
| 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 8 : juste dans les deux lectures |
C = 1, V = 0 : (−1) + (−1)
| 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | retenues | ||
| 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 255 non signé, −1 signé | ||
| + | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 255 non signé, −1 signé | |
| 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 | non signé 254 : faux ; signé −2 : juste |
En signé, le résultat −2 est juste. En non signé, ces bits valent 255 + 255 = 510, qui ne tient pas sur 8 bits : la retenue le signale.
C = 0, V = 1 : 100 + 50
| 1 | 1 | retenues | ||||||||
| 0 | 1 | 1 | 0 | 0 | 1 | 0 | 0 | 100 | ||
| + | 0 | 0 | 1 | 1 | 0 | 0 | 1 | 0 | 50 | |
| 1 | 0 | 0 | 1 | 0 | 1 | 1 | 0 | non signé 150 : juste ; signé −106 : faux |
Positif + positif donne un nombre qui commence par 1 : négatif. Le vrai résultat, 150, dépasse 127. En non signé, en revanche, 100 + 50 = 150 est juste.
C = 1, V = 1 : (−100) + (−50)
| 1 | 1 | 1 | 1 | retenues | ||||||
| 1 | 0 | 0 | 1 | 1 | 1 | 0 | 0 | 156 non signé, −100 signé | ||
| + | 1 | 1 | 0 | 0 | 1 | 1 | 1 | 0 | 206 non signé, −50 signé | |
| 1 | 0 | 1 | 1 | 0 | 1 | 0 | 1 | 0 | non signé 106 : faux ; signé 106 : faux |
Négatif + négatif donne un positif : −150 est en dessous de −128. Faux dans les deux lectures.
Laboratoire : le cercle des 4 bits
Voici l'horloge de la section 6.4, pour 4 bits. À l'extérieur, la lecture non signée (0 à 15) ; à l'intérieur, le complément à deux (−8 à 7). Clique sur une case pour choisir A, et règle B avec ses 4 bits. L'arc extérieur montre l'addition non signée : s'il franchit la frontière du haut (15 → 0), C = 1. L'arc intérieur montre l'addition signée : s'il franchit la frontière du bas (7 → −8), V = 1. Les deux arcs arrivent sur la même case : ce sont les mêmes bits, lus de deux façons.
7.5 Laboratoire : une mini-UAL sur 8 bits
Tape deux nombres entre −128 et 255, ou deux suites de 8 bits, puis choisis + ou −. La page applique la méthode de la section 7.2 et affiche les indicateurs C et V, avec les deux lectures du résultat.
7.6 Pourquoi ça compte en sécurité
Débordement d'entier (integer overflow)
En Python, un entier grandit autant qu'il faut : pas de débordement. Mais dans les langages où les entiers ont une taille fixe (C, C++, Java, Rust compilé en mode release), un débordement peut passer inaperçu. C'est une famille de failles bien connue, répertoriée sous le nom CWE-190 (Integer Overflow or Wraparound) : un calcul de taille qui déborde donne un petit nombre, et un test de sécurité passe alors qu'il devrait échouer. En C ou en C++, le programme peut alors écrire en dehors de la mémoire prévue ; Java et Rust vérifient les bornes des tableaux et s'arrêtent sur une erreur. En C, le débordement d'un entier signé n'est même pas garanti de « faire le tour » : c'est un comportement indéfini.
Et ça te concerne aussi en IA : les modèles quantifiés stockent leurs poids en int8, c'est-à-dire en complément à deux sur 8 bits, de −128 à 127. Tu peux le voir sur ta machine :
>>> import numpy as np
>>> np.array([127], dtype=np.int8) + 1
array([-128], dtype=int8)
127 + 1 = −128 : on vient de franchir la frontière du bas du cercle.
Vérifie-toi (section 7)
Sur 8 bits en complément à deux, que donne 100 + 100 ?
Peut-il y avoir débordement en calculant 120 + (−120) ?
Pour calculer 30 − 12 en complément à deux, la machine calcule…
Une retenue sort à gauche pendant une addition en complément à deux. Le résultat signé est…
À poser sur ta feuille, puis à vérifier
- Calcule 75 − 90 sur 8 bits.
Réponse
75 = 0100 1011 ; −90 = 1010 0110 (90 = 0101 1010, inversé 1010 0101, + 1). Somme : 1111 0001, pas de retenue, pas de débordement. Lecture : −128 + 64 + 32 + 16 + 1 = −15. - Calcule −100 − 30 sur 8 bits. Que remarques-tu ?
Réponse
−100 = 1001 1100 ; −30 = 1110 0010. Somme : 1 0111 1110, on ignore la retenue : 0111 1110 = 126. Négatif + négatif = positif : débordement, V = 1. Le vrai résultat, −130, est en dessous de −128. - Calcule 127 + 1 sur 8 bits, et compare avec la sortie de NumPy en 7.6.
Réponse
0111 1111 + 0000 0001 = 1000 0000 = −128. Débordement : c'est exactement ce qu'affiche NumPy.
8Aperçu : caractères et nombres à virgule
Le programme de la séance du 28 septembre mentionne un « aperçu » de ces deux codages. Voici l'essentiel.
8.1 Les caractères
Un texte est une suite de nombres : chaque caractère a un numéro, fixé par une table. La plus ancienne, ASCII, numérote 128 caractères sur 7 bits.
| caractère | décimal | hexa | binaire |
|---|---|---|---|
| espace | 32 | 20 | 0010 0000 |
| '0' | 48 | 30 | 0011 0000 |
| '9' | 57 | 39 | 0011 1001 |
| 'A' | 65 | 41 | 0100 0001 |
| 'Z' | 90 | 5A | 0101 1010 |
| 'a' | 97 | 61 | 0110 0001 |
- Le caractère '7' n'est pas le nombre 7 : il vaut 55. Pour retrouver le chiffre, on soustrait le code de '0' : 55 − 48 = 7.
- Une minuscule et sa majuscule diffèrent de 32 = 0010 0000 : un seul bit. Changer la casse, c'est inverser ce bit.
- En Python,
ord('A')donne 65 etchr(97)donne 'a'.
Aujourd'hui, on utilise Unicode, qui numérote plus de 150 000 caractères, et UTF-8, qui les écrit sur 1 à 4 octets. Les caractères ASCII gardent leur octet unique ; « é » prend 2 octets, C3 A9. Si un texte UTF-8 est relu octet par octet comme un ancien codage (Latin-1), chaque octet devient un caractère, et « é » s'affiche « é ». Tu as sûrement déjà vu ce bug sur des sites mal configurés.
8.2 Les nombres à virgule
Virgule fixe. On prolonge les poids après la virgule : 2⁻¹ = 0,5, 2⁻² = 0,25, 2⁻³ = 0,125… Ainsi (101,1)₂ = 4 + 1 + 0,5 = 5,5.
Virgule flottante (floating point). On écrit le nombre comme en notation scientifique, 6,02 × 10²³, mais en base 2 : un bit de signe, un exposant, et une mantisse (significand) qui contient les chiffres significatifs. La norme IEEE 754 fixe deux formats courants :
| format | total | signe | exposant | mantisse |
|---|---|---|---|---|
simple précision (float) | 32 bits | 1 | 8 | 23 |
double précision (double, le float de Python) | 64 bits | 1 | 11 | 52 |
Conséquence importante : 0,1 n'a pas d'écriture binaire finie. Il s'écrit (0,000110011001100…)₂, avec une suite qui se répète sans fin, comme 1/3 = 0,333… en décimal. La machine doit arrondir, et :
>>> 0.1 + 0.2
0.30000000000000004
>>> 0.1 + 0.2 == 0.3
False
Évite donc de comparer deux flottants avec ==. En Python, utilise plutôt math.isclose.
9Relecture de tes notes
Ce qui est juste
- Toutes tes conversions : (1011011)₂ = 91, 110110 = 54, 72 = 0100 1000, 167 = 1010 0111 = (247)₈, 1 495 = (2727)₈ = (5D7)₁₆, 267 = (413)₈ = (10B)₁₆, (25)₉ = 23, (ACDC)₁₆ = (126334)₈.
- Ton tableau des entiers de 0 à 21, et les règles « paquets de 3 pour l'octal, paquets de 4 pour l'hexadécimal ».
- Les additions binaires (1011 + 0111, 7 + 9, 14 + 15), l'addition ABBA + ACDC en hexadécimal, les soustractions 1E9 − 8A = 15F et 2026 − 1999 = 27.
- Les compléments à deux de −32 et de −58, et le « un seul zéro » du complément à deux.
Ce qu'il faut corriger
- −7 en complément à un (page 6). 1110 0000 est le miroir de 0000 0111, pas son inversion. Complément à un : 1111 1000 ; complément à deux : 1111 1001 (section 6.3).
- La liste de −7 à −11 (page 6). Les valeurs 1111 1000, 1111 0111, 1111 0110, 1111 0101, 1111 0100 sont en complément à un. Écris-le à côté. En complément à deux, chaque valeur a 1 de plus : −7 = 1111 1001, −8 = 1111 1000, −9 = 1111 0111, −10 = 1111 0110, −11 = 1111 0101. Complète les lignes −12 à −15, restées vides, dans les deux conventions.
- 32 + (−58) et 58 + (−32) (page 7). Tu as utilisé −32 au lieu de 32, puis −58 au lieu de 58. Tes additions calculent en fait (−32) + (−58) = −90 (section 7.3).
- L'addition en octal (page 8). 125672 + 126334 = 254226, pas 154226 : dans la colonne de gauche, 1 + 1 = 2. Vérification : 43 962 + 44 252 = 88 214 = (254226)₈.
- Un titre inversé (page 7). 1010 1011 1011 1010 → (125672)₈ est la conversion de ABBA, pas de ACDC.
- Le complément à un sur 16 bits (page 8). La retenue circulaire s'ajoute une seule fois : le résultat est 0000 0111 0101 1110 = 1 886 (section 6.3).
- « 1000 0000 = −0 », « 1000 0001 = −1 » (page 5) : c'est juste, mais seulement en signe et valeur absolue. « −0 = 1111 1111 » est du complément à un, et « −1 = 1111 1111 » du complément à deux. Écris toujours la convention à côté d'un nombre signé : la même suite de bits change de valeur d'une convention à l'autre.
- « UAL : addition seulement » (page 5). L'UAL (unité arithmétique et logique, ALU) fait aussi des opérations logiques (ET, OU, XOR…) : c'est le L de UAL. Ce qui est vrai, c'est qu'il n'y a pas de circuit de soustraction séparé (section 7.1).
- « RAM : donne les instructions au processeur » (page 5). La RAM ne fait rien d'elle-même : elle stocke les instructions et les données, et c'est le processeur qui va les chercher. Tu verras ce cycle le 16 novembre.
- « 32 cases = 2³¹ » (page 5). Sur 32 bits, il y a 2³² motifs. L'idée de tes notes, c'est qu'un bit sert au signe : en complément à deux, on va de −2³¹ à 2³¹ − 1, soit environ ± 2,1 milliards.
10Bilan
Avant l'évaluation du 2 novembre, tu dois pouvoir, sans tes notes…
- dire combien de valeurs on écrit avec n bits, et combien de bits il faut pour N valeurs ;
- convertir entre les bases 2, 8, 10 et 16 dans tous les sens, et expliquer pourquoi on lit les restes de bas en haut ;
- poser une addition et une soustraction en base 2, 8 et 16, avec retenues et emprunts ;
- coder un entier en signe et valeur absolue, en complément à un et en complément à deux, et dire les défauts des deux premiers ;
- expliquer pourquoi « inverser puis + 1 » donne l'opposé (l'horloge modulo 256) ;
- calculer A + B et A − B en complément à deux, et dire s'il y a retenue, débordement, les deux ou aucun ;
- lire une même suite de bits en non signé et en complément à deux.
La suite : la page Les portes logiques, depuis le tout début, pour la séance du 5 octobre. Tu y verras comment deux portes suffisent pour additionner deux bits.