Représentation des nombres et du texte : bases, complément à 2, flottants et codage des caractères
Lucas tape dans la console Python l'instruction 0.1 + 0.2 == 0.3 et obtient… False. Un bug de Python ? Non : un ordinateur ne sait manipuler que des 0 et des 1, et certains nombres décimaux très simples n'ont pas d'écriture exacte en binaire. Dans cette page, tu vas voir comment une machine représente les entiers, les nombres à virgule et les textes, et tu sauras expliquer ce résultat étonnant.
Écrire un entier dans une base b
Dans la vie courante, on écrit les nombres en base 10 : chaque chiffre est multiplié par une puissance de 10 (unités, dizaines, centaines…). Une machine travaille avec deux états (courant ou non), donc en base 2 : chaque chiffre, appelé bit, vaut 0 ou 1 et est multiplié par une puissance de 2.
Les bases utilisées en informatique sont la base 2 (binaire), la base 10 (décimale) et la base 16 (hexadécimale), qui utilise les chiffres 0–9 puis A=10, B=11, C=12, D=13, E=14, F=15.
Chaque case a pour poids une puissance de 2 : on additionne les poids des cases contenant un 1.
En Python, 0b1011 et 0xFF sont des entiers écrits en binaire et en hexadécimal. Les fonctions bin(183) et hex(183) renvoient les chaînes '0b10110111' et '0xb7', et int("10110111", 2) fait la conversion inverse.
a) Convertir $(1101\,0110)2$ en base 10. b) Convertir 183 en base 2. c) Convertir $(2F){16}$ en base 10 puis en base 2.
- a) Convertir $(1101\,0110)_2$ en base 10.
- b) Convertir 183 en base 2.
- c) Convertir $(2F)_{16}$ en base 10 puis en base 2.
Combien de bits faut-il ?
Avec $n$ bits, on peut former $2^n$ combinaisons différentes (chaque bit double le nombre de possibilités). Si on les utilise pour des entiers positifs (non signés), on représente les entiers de $0$ à $2^n - 1$.
| Nombre de bits $n$ | 4 | 8 | 16 | 32 | 64 |
|---|---|---|---|---|---|
| Valeurs possibles $2^n$ | 16 | 256 | 65 536 | 4 294 967 296 | environ $1{,}8 \times 10^{19}$ |
| Plus grand entier non signé | 15 | 255 | 65 535 | 4 294 967 295 | $2^{64}-1$ |
Les tailles usuelles sont 8, 16, 32 et 64 bits. Un groupe de 8 bits s'appelle un octet (symbole o). Pour mesurer des tailles, on utilise les unités du système international : $1\,\text{ko} = 1\,000$ octets, $1\,\text{Mo} = 10^6$ octets, $1\,\text{Go} = 10^9$ octets, $1\,\text{To} = 10^{12}$ octets. Les unités kio, Mio, Gio désignent les puissances de 1 024 ($1\,\text{kio} = 1\,024$ octets).
Pourquoi ? Si $N < 2^n$, alors son écriture n'a pas de bit à la position $n$ ou au-delà. Deux nombres inférieurs à $2^n$ ont une somme inférieure à $2^{n+1}$ et un produit inférieur à $2^{2n}$.
a) Combien de bits faut-il au minimum pour écrire l'entier 300 en binaire ? b) Combien de valeurs différentes peut-on représenter avec 10 bits ? c) Quel est le plus…
- a) Combien de bits faut-il au minimum pour écrire l'entier 300 en binaire ?
- b) Combien de valeurs différentes peut-on représenter avec 10 bits ?
- c) Quel est le plus grand entier non signé représentable sur 12 bits ?
On code une image en niveaux de gris de 1 920 × 1 080 pixels, chaque pixel étant codé sur 8 bits. a) Calculer la taille de l'image non compressée en octets, puis en Mo…
On code une image en niveaux de gris de 1 920 × 1 080 pixels, chaque pixel étant codé sur 8 bits.
- a) Calculer la taille de l'image non compressée en octets, puis en Mo (1 Mo = $10^6$ octets).
- b) On passe à une image couleur avec 3 octets par pixel. Calculer la nouvelle taille et le nombre de couleurs possibles.
- c) Une vidéo de 25 images par seconde de cette image couleur dure 90 minutes. Calculer le volume brut en To et expliquer pourquoi la compression est indispensable.
Les entiers relatifs : le complément à 2
Comment coder $-25$ avec seulement des 0 et des 1 ? On pourrait réserver un bit pour le signe, mais l'addition deviendrait compliquée. Le complément à 2 a un grand avantage : la même addition binaire fonctionne pour les nombres positifs et négatifs.
Sur 3 bits, par exemple :
| Écriture | 000 | 001 | 010 | 011 | 100 | 101 | 110 | 111 |
|---|---|---|---|---|---|---|---|---|
| Valeur | 0 | 1 | 2 | 3 | −4 | −3 | −2 | −1 |
Sur 8 bits, la plage est donc $[-128 ; 127]$.
Avec le complément à 2, une soustraction devient une addition : $a - b = a + (-b)$, en ignorant la retenue qui sort du dernier bit.
L'addition reste correcte tant que le résultat est dans la plage : les représentations sont des entiers de $[0 ; 2^n - 1]$ qui valent la valeur réelle modulo $2^n$, et on retombe sur le bon représentant si le résultat est dans la plage.
a) Donner la représentation en complément à 2 sur 8 bits de $+25$ et de $-25$. b) Quelle est la plage des entiers représentables en complément à 2 sur 8 bits ? c) Quel…
- a) Donner la représentation en complément à 2 sur 8 bits de $+25$ et de $-25$.
- b) Quelle est la plage des entiers représentables en complément à 2 sur 8 bits ?
- c) Quel entier est représenté par $(1111\,1100)_2$ en complément à 2 sur 8 bits ?
a) Effectuer l'addition binaire $(0110\,1101)2 + (0010\,1011)2$ et vérifier en base 10. b) Calculer en complément à 2 sur 8 bits $17 - 42$ en additionnant 17 et la…
- a) Effectuer l'addition binaire $(0110\,1101)_2 + (0010\,1011)_2$ et vérifier en base 10.
- b) Calculer en complément à 2 sur 8 bits $17 - 42$ en additionnant 17 et la représentation de $-42$. Donner le résultat en binaire et en décimal.
- c) Dans quel cas y a-t-il dépassement de capacité en complément à 2 ?
a) Montrer que pour représenter tous les entiers de 0 à $N$ il faut $\lfloor \log_2 N \rfloor + 1$ bits (on suppose $N \geq 1$). b) Montrer que l'opposé d'un entier $x$…
- a) Montrer que pour représenter tous les entiers de 0 à $N$ il faut $\lfloor \log_2 N \rfloor + 1$ bits (on suppose $N \geq 1$).
- b) Montrer que l'opposé d'un entier $x$ tel que $0 < x < 2^{n-1}$ en complément à 2 sur $n$ bits s'obtient comme $2^n - x$, et que cela revient à inverser les bits puis ajouter 1.
- c) En déduire que l'addition de deux entiers en complément à 2 sur $n$ bits est correcte tant que le résultat reste dans $[-2^{n-1}, 2^{n-1}-1]$.
Les nombres à virgule : les flottants
Pour écrire un nombre à virgule en binaire, on utilise les puissances négatives de 2 : $2^{-1} = 0{,}5$, $2^{-2} = 0{,}25$, $2^{-3} = 0{,}125$, etc.
Faisons la même chose avec $0{,}1$ : $0{,}1 \to 0{,}2 \to 0{,}4 \to 0{,}8 \to 1{,}6 \to 1{,}2 \to 0{,}4 \to 0{,}8 \to 1{,}6\dots$ Les bits obtenus sont $0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1\dots$ et le motif 1100 se répète sans fin :
De même, $\frac13 = (0{,}010101\dots)_2$. Ces nombres ont une écriture infinie en binaire (comme $\frac13 = 0{,}333\dots$ en décimal). Comme la mémoire est finie, la machine tronque : elle stocke une valeur approchée.
Un exemple avec un format simplifié sur 8 bits (1 bit de signe, 3 bits d'exposant avec biais 3, 4 bits de mantisse) : le mot $(0\,101\,0110)_2$ a pour signe $s = 0$, exposant $e = (101)_2 = 5$ et mantisse $1{,}0110$. Sa valeur est $1{,}0110_2 \times 2^{5-3} = 1{,}375 \times 4 = 5{,}5$.
Comme l'exposant déplace la virgule, les flottants ne sont pas régulièrement répartis : dans ce format, l'écart entre deux flottants voisins est $2^{-4} \times 2^{e-3}$ ; il double chaque fois que $e$ augmente de 1. Il y a beaucoup de flottants près de 0 et de moins en moins quand les valeurs grandissent.
Retour au début : 0.1 et 0.2 sont stockés avec une petite erreur, leur somme n'est donc pas exactement le flottant le plus proche de 0,3, d'où False.
a) Convertir le nombre décimal $0,625$ en binaire. b) Écrire $0,1$ en binaire sur les 8 premiers chiffres après la virgule et expliquer pourquoi 0.1 + 0.2 == 0.3 vaut…
- a) Convertir le nombre décimal $0,625$ en binaire.
- b) Écrire $0,1$ en binaire sur les 8 premiers chiffres après la virgule et expliquer pourquoi
0.1 + 0.2 == 0.3vautFalseen Python.
- c) Écrire les trois champs (signe, exposant, mantisse) d'un flottant en double précision et donner leur nombre de bits.
On étudie un format simplifié de flottant sur 8 bits : 1 bit de signe, 3 bits d'exposant (biais 3) et 4 bits de mantisse, avec la valeur…
On étudie un format simplifié de flottant sur 8 bits : 1 bit de signe, 3 bits d'exposant (biais 3) et 4 bits de mantisse, avec la valeur $(-1)^s \times 1,m \times 2^{e-3}$.
- a) Décoder $(0\,101\,0110)_2$.
- b) Quel est le plus petit réel strictement positif représentable (avec exposant non nul) ?
- c) Montrer que l'écart entre deux flottants consécutifs double quand l'exposant augmente de 1, et en déduire pourquoi les flottants ne sont pas régulièrement répartis.
Représenter du texte
Un texte est une suite de caractères. Pour le stocker, on associe à chaque caractère un entier : son point de code, ensuite écrit en binaire. Plusieurs normes existent.
-
ASCII : 128 caractères codés sur 7 bits (lettres sans accent, chiffres, ponctuation, caractères de contrôle). Par exemple
A= 65 = $(41)_{16}$ eta= 97 = $(61)_{16}$. -
ISO 8859-1 (latin-1) : 256 caractères codés sur un octet. Elle reprend l'ASCII et ajoute les lettres accentuées d'Europe occidentale :
é= 233 = $(\mathrm{E9})_{16}$. Mais elle ne contient ni€, ni les alphabets non latins. -
Unicode : un répertoire de plus de 150 000 caractères de toutes les écritures (accents, alphabets, emojis). UTF-8 est le codage le plus répandu : il utilise 1 à 4 octets par caractère. Les caractères ASCII restent sur 1 octet,
éen prend 2.
Entre A et a, il y a toujours 32 d'écart : a = A + 32, car seul le bit de poids 32 change (0100 0001 devient 0110 0001).
En Python, ord('A') renvoie 65, chr(97) renvoie 'a', et "é".encode("utf-8") donne deux octets (b'\\xc3\\xa9').
a) Donner le code ASCII (en décimal puis en hexadécimal) de A (65) et de a. Quelle relation lie majuscule et minuscule ? b) Expliquer la différence entre ASCII, ISO…
- a) Donner le code ASCII (en décimal puis en hexadécimal) de
A(65) et dea. Quelle relation lie majuscule et minuscule ?
- b) Expliquer la différence entre ASCII, ISO 8859-1 et UTF-8 et dire combien d'octets occupe
éen UTF-8.
- c) Un fichier texte de 2 000 caractères ASCII est enregistré en UTF-8. Quelle est sa taille en octets ? Et si tous les caractères sont des
é?
L'essentiel
-
Un entier s'écrit en base $b$ avec des chiffres de $0$ à $b-1$ ; on passe de la base 2 à la base 16 en groupant les bits par 4.
-
Avec $n$ bits, on obtient $2^n$ valeurs, donc les entiers de $0$ à $2^n - 1$. Pour écrire $N$, il faut $\lfloor \log_2 N \rfloor + 1$ bits.
-
En complément à 2 sur $n$ bits, on représente $[-2^{n-1} ; 2^{n-1} - 1]$ ; on calcule l'opposé en inversant les bits puis en ajoutant 1, et l'addition binaire habituelle reste valable.
-
Les flottants sont des valeurs approchées (1 + 11 + 52 bits en double précision) : on ne les compare pas avec
==. -
Un texte est une suite d'entiers : ASCII sur 7 bits, ISO 8859-1 sur 1 octet, UTF-8 sur 1 à 4 octets.