School 47

Des 0 et des 1 pour tout dire : entiers, flottants et caractères en machine

Première · Numérique & code · environ 20 min

Début décembre 2014, le clip Gangnam Style dépasse 2 147 483 647 vues : le plus grand entier qu'on peut écrire sur 32 bits en complément à deux. YouTube avait déjà passé son compteur à 64 bits. Et ce message où « été » s'affiche « été » ? Des octets mal lus. Dans un ordinateur, entiers, nombres à virgule et lettres ne sont que des suites de 0 et de 1.

1. Le binaire, ou base 2

En base 2, il n'existe que deux chiffres, 0 et 1 (les bits), et les rangs valent 1, 2, 4, 8, 16, 32… : les puissances de 2. Ainsi, 101101 en binaire vaut 32 + 8 + 4 + 1 = 45.

Dans l'autre sens, on divise par 2 jusqu'à un quotient nul et on lit les restes de bas en haut : 45 = 2 × 22 + 1 ; 22 = 2 × 11 + 0 ; 11 = 2 × 5 + 1 ; 5 = 2 × 2 + 1 ; 2 = 2 × 1 + 0 ; 1 = 2 × 0 + 1. Du dernier reste au premier : 101101.

Avec n bits, on écrit 2ⁿ valeurs, de 0 à 2ⁿ − 1. Un octet (8 bits) va donc de 0 à 255.

2. L'hexadécimal, le binaire en abrégé

La base 16 utilise 0 à 9, puis A (10) à F (15). Son atout : un chiffre hexadécimal = 4 bits. On découpe 10110110 en 1011 et 0110, soit B et 6 : l'octet s'écrit B6 et vaut 11 × 16 + 6 = 182. En CSS, #FF8000 donne rouge FF = 255, vert 80 = 128, bleu 00 = 0 : un orange.

print(bin(45)) # 0b101101
print(hex(182)) # 0xb6
print(int("101101", 2)) # 45
print(0xB6) # 182

3. Les entiers négatifs : le complément à deux

Sur 8 bits, on code aussi les négatifs, de −128 à 127. Pour coder −x, on écrit x sur 8 bits, on inverse tous les bits, puis on ajoute 1.

Exemple : 5 = 00000101 → inversé : 11111010 → plus 1 : 11111011, qui code −5.

Vérifions : 11111011 + 00000101 = 1 00000000 ; le neuvième bit sort de l'octet, il reste 0, comme −5 + 5. Astuce : le bit de gauche pèse −128 au lieu de +128, d'où 11111011 = −128 + 64 + 32 + 16 + 8 + 2 + 1 = −5. Un octet qui commence par 1 code un négatif.

Gare au dépassement : sur 8 bits, 127 + 1 donne 10000000, soit −128 !

4. Les nombres à virgule : des flottants approchés

Un réel est stocké en notation scientifique de base 2 (signe, exposant, mantisse ; norme IEEE 754, 64 bits en Python) : c'est un flottant.

0,25 = 14 s'écrit exactement : 0,01 en binaire. Mais 0,1 donne 0,000110011001100… sans fin, comme 1/3 = 0,333… en base 10. La machine coupe : 0,1 n'est stocké qu'approximativement.

print(0.1 + 0.2) # 0.30000000000000004
print(0.1 + 0.2 == 0.3) # False
print(abs((0.1 + 0.2) - 0.3) < 1e-9) # True

Règle d'or : on ne teste jamais l'égalité de deux flottants, on vérifie que leur écart est minuscule.

5. Les caractères : d'ASCII à Unicode

Chaque caractère reçoit un numéro. L'ASCII (1963) code 128 caractères sur 7 bits : A = 65, a = 97, le chiffre 0 = 48, l'espace = 32. Aucun accent ! Les tables sur 8 bits, comme Latin-1 (ISO 8859-1), offrent 128 places de plus, mais chaque région avait la sienne.

Unicode donne à chaque caractère de toutes les écritures, emojis compris, un numéro unique : son point de code, noté U+… (plus de 150 000). é est U+00E9 (233), € est U+20AC, est U+1F600. L'encodage UTF-8 écrit ces numéros sur 1 à 4 octets : un seul pour les 128 caractères ASCII, 2 pour é, 3 pour €, 4 pour .

print(ord("A"), chr(97)) # 65 a
print(list("é".encode("utf-8"))) # [195, 169]
print(len("été".encode("utf-8"))) # 5

Mystère résolu : les deux octets de é, 195 et 169 (C3 et A9), lus en Latin-1, deviennent deux caractères, Ã et ©.

À retenir

  • Divisions successives par 2 pour écrire un entier en base 2 ; n bits donnent 2ⁿ valeurs (un octet : 0 à 255).
  • Un chiffre hexadécimal vaut 4 bits : B6 = 10110110 = 182.
  • Complément à deux : pour coder −x, on inverse les bits de x puis on ajoute 1 ; sur 8 bits, de −128 à 127.
  • Les flottants sont approchés : on ne teste jamais leur égalité, on compare leur écart.
  • ASCII code 128 caractères sur 7 bits ; Unicode numérote tous les caractères, UTF-8 les écrit sur 1 à 4 octets.

★ Pour aller plus loin

Le 4 juin 1996, pour son premier vol, Ariane 5 se désintègre une quarantaine de secondes après l'allumage de ses moteurs : un flottant sur 64 bits, lié à la vitesse horizontale, converti en entier signé sur 16 bits, a provoqué un dépassement qui a mis hors service ses centrales inertielles.

Prochain bug annoncé : de nombreux systèmes comptent les secondes depuis le 1er janvier 1970 sur 32 bits signés. Le 19 janvier 2038 à 3 h 14 min 7 s (UTC), ce compteur dépassera 2 147 483 647 et basculera en décembre 1901. Remède : 64 bits.

Sources pour creuser

  • Spécialité NSI (Numérique et sciences informatiques) : 30 leçons avec exercices corrigés – Première, Thibaut Balabonski, Sylvain Conchon, Jean-Christophe Filliâtre et Kim Nguyen (Ellipses).
  • Apprendre à programmer avec Python 3, Gérard Swinnen (Eyrolles).
  • docs.python.org/fr : le chapitre 15 du tutoriel (nombres à virgule flottante).
  • YouTube : les chaînes Graven - Développement et Docstring (Python en français) ; sur lumni.fr, cherche « codage binaire ».
  • unicode.org/charts et le programme de NSI sur eduscol.education.fr.