Skip to content

Fondamentaux · Chapitre F.2

Binaire et hexadécimal

Le fonctionnement des systèmes de numération positionnels, pourquoi les ordinateurs comptent en base 2, comment convertir à la main entre décimal, binaire, hexadécimal et octal (avec 2026 comme exemple), pourquoi un chiffre hexadécimal vaut exactement quatre bits, et ce que sont bits, quartets, octets et mots.

Les ordinateurs stockent tout sous forme de bits, des valeurs qui valent 0 ou 1. Nombres, texte, pixels, instructions : tout finit en suites de bits. Pour les lire, il faut être à l’aise avec la base 2 (le binaire) et avec son abréviation, la base 16 (l’hexadécimal). Ce chapitre construit les deux à partir de zéro.

La notation positionnelle

Le nombre décimal 2026 signifie 2 milliers, 0 centaine, 2 dizaines et 6 unités :

2026 = 2×10³ + 0×10² + 2×10¹ + 6×10⁰

Chaque position vaut dix fois celle de droite. Dix est la base. Rien dans la méthode ne dépend de dix : en base b, il faut b symboles de chiffres, de 0 à b − 1, et chaque position vaut b fois celle de droite. Cela marche aussi à droite de la virgule, avec des puissances négatives : 0,25 vaut 2×10⁻¹ + 5×10⁻².

Les bases qui comptent en informatique sont :

BaseNomChiffresS’écrit en C, Python, JavaScript
2binaire0 10b11111101010
8octal0–70o3752 (Python, JavaScript), 03752 (C)
10décimal0–92026
16hexadécimal0–9, A–F0x7EA

Quand la base n’est pas évidente, on l’écrit en indice : 111₂ vaut sept, 111₁₀ cent onze, 111₁₆ vaut 273.

Pourquoi le binaire

Un circuit pourrait en principe distinguer dix niveaux de tension, mais il devrait séparer de façon fiable 0,5 V de 0,6 V, malgré le bruit, la température et les variations de fabrication. Deux niveaux, « bas » et « haut », avec une large marge de sécurité entre eux, sont bien plus faciles à construire et bien plus robustes. Le niveau de la logique numérique repose exactement là-dessus : chaque fil porte un bit.

En binaire, chaque position vaut deux fois celle de droite :

11111101010₂ = 1×2¹⁰ + 1×2⁹ + 1×2⁸ + 1×2⁷ + 1×2⁶ + 1×2⁵ + 0×2⁴ + 1×2³ + 0×2² + 1×2¹ + 0×2⁰
             = 1024 + 512 + 256 + 128 + 64 + 32 + 8 + 2
             = 2026

Il est utile de connaître par cœur les premières puissances de deux :

n012345678101632
2ⁿ12481632641282561 02465 5364 294 967 296

n bits représentent 2ⁿ valeurs différentes : un octet de 8 bits a 256 motifs, de 0 à 255 lu comme nombre non signé ; 16 bits donnent 0 à 65 535 ; 32 bits, 0 à 4 294 967 295. La façon de représenter les nombres négatifs fait l’objet du chapitre sur le complément à deux.

Convertir du décimal vers le binaire

Il y a deux méthodes classiques.

Soustraire des puissances de deux. Prendre la plus grande puissance de deux qui tient, la soustraire, et recommencer. 2026 − 1024 = 1002 ; − 512 = 490 ; − 256 = 234 ; − 128 = 106 ; − 64 = 42 ; − 32 = 10 ; − 8 = 2 ; − 2 = 0. Les puissances utilisées sont 2¹⁰, 2⁹, 2⁸, 2⁷, 2⁶, 2⁵, 2³ et 2¹ : on met un 1 à ces positions et un 0 ailleurs, ce qui donne 11111101010.

Diviser par deux, encore et encore. Diviser par 2 et noter le reste ; continuer avec le quotient jusqu’à 0. Les restes, lus du dernier au premier, sont les chiffres binaires :

Nombre÷ 2Reste
202610130 ← bit de poids faible
10135061
5062530
2531261
126630
63311
31151
1571
731
311
101 ← bit de poids fort

En remontant : 11111101010. La même méthode vaut pour toute base : diviser par 16 donne les chiffres hexadécimaux, par 8 les chiffres octaux.

Dans l’autre sens, la méthode la plus rapide à la main est le doublement : partir de 0 et, pour chaque bit de gauche à droite, doubler le total et ajouter le bit. Pour 11111101010 : 1, 3, 7, 15, 31, 63, 126, 253, 506, 1013, 2026. C’est aussi exactement ainsi qu’un programme lit un nombre dans un texte, un chiffre à la fois.

Les fractions

À droite de la virgule binaire, les positions valent ½, ¼, ⅛, etc. Pour convertir une fraction décimale, on la multiplie par 2 à répétition en prenant chaque fois la partie entière : 0,625 × 2 = 1,25, 0,25 × 2 = 0,5, 0,5 × 2 = 1,0, donc 0,625 = 0,101₂ (½ + ⅛).

Beaucoup de fractions décimales simples n’ont pas d’écriture binaire finie. 0,1 × 2 donne 0,2, 0,4, 0,8, 1,6, 1,2, 0,4… et le motif se répète indéfiniment : 0,1 = 0,000110011001100…₂, tout comme ⅓ = 0,333… en décimal. Un ordinateur doit bien couper quelque part, ce qui explique que 0,1 ne puisse pas être stocké exactement. Le chapitre sur la virgule flottante reprend à partir de là.

L’hexadécimal : quatre bits par chiffre

Les longues suites binaires sont difficiles à lire et faciles à mal recopier. L’hexadécimal règle le problème grâce à une propriété : 16 = 2⁴, donc chaque chiffre hexadécimal représente exactement quatre bits, et la conversion se fait groupe par groupe, sans aucun calcul. Les chiffres après 9 sont A (10) à F (15) :

HexBinaireDécHexBinaireDéc
000000810008
100011910019
200102A101010
300113B101111
401004C110012
501015D110113
601106E111014
701117F111115

Pour passer du binaire à l’hexadécimal, on découpe les bits en groupes de quatre en partant de la droite, et on remplace chaque groupe :

2026 = 111 1110 1010₂
     =   7    E    A   = 0x7EA

Et dans l’autre sens : 0xC0FFEE s’écrit 1100 0000 1111 1111 1110 1110, 24 bits, soit 12 648 430 en décimal. Un octet fait toujours exactement deux chiffres hexadécimaux, de 00 à FF, et c’est pourquoi l’hexadécimal est la façon standard de montrer la mémoire, le code machine, les paquets réseau et le contenu des fichiers. L’outil xxd, par exemple, montre les quatre octets du texte « Hi! » suivi d’un saut de ligne :

$ printf 'Hi!\n' | xxd
00000000: 4869 210a                                Hi!.

48 est H, 69 est i, 21 est !, 0a est le saut de ligne : ce sont les codes de caractères du chapitre sur le texte. Les couleurs du web (#FF8800 : rouge 255, vert 136, bleu 0), les adresses mémoire d’un débogueur et les octets des instructions x86 s’écrivent tous en hexadécimal pour la même raison.

Dans le simulateur, chaque registre est affiché en hexadécimal et en décimal. Décaler de 4 bits vers la gauche ajoute un zéro hexadécimal, décaler de 4 vers la droite retire le dernier chiffre hexadécimal, et un ET avec 0xF ne garde que le dernier, parce que chaque chiffre hexadécimal est un groupe de 4 bits :

Live · Un chiffre hexadécimal, c’est quatre bits

À essayer : Appuyez sur Step pour exécuter une instruction, Run pour animer ou Continue pour aller au bout ; les boutons L2 à L7 changent de niveau, vers le bas ou le haut.

program· ▸ is the next instruction
  1. mov eax, 2026 ; 0x7EA
  2. mov ebx, 0x7EA ; the same value, written in hex
  3. mov ecx, 0b11111101010 ; and in binary
  4. shl eax, 4 ; 0x7EA0: one hex digit appended
  5. shr ebx, 4 ; 0x7E: the last hex digit dropped
  6. and ecx, 0xF ; 0xA: only the last hex digit kept
step 0
Loading emulator…
The instruction that just ran, as the bytes the CPU actually fetched and decoded.

Les trois premières instructions chargent le même nombre, écrit de trois façons : l’assembleur les convertit toutes vers les mêmes bits. Après les décalages, eax vaut 0x7EA0 (32 416 = 2026 × 16), ebx vaut 0x7E (126 = 2026 ÷ 16, arrondi vers le bas) et ecx vaut 0xA (10). Le shr met aussi l’indicateur de retenue à 1 : c’est le dernier bit sorti, le bit 3 de 1010.

L’octal

L’octal fait la même chose avec des groupes de trois bits : 2026 = 11 111 101 010₂ = 3752₈. Il était populaire sur les machines dont la taille de mot était un multiple de 3 (le PDP-8 à 12 bits, les machines à 36 bits comme l’IBM 7094), où un mot fait un nombre entier de chiffres octaux. Sur les machines actuelles à 8, 16, 32 et 64 bits, l’hexadécimal convient mieux, et l’octal ne survit guère qu’à un endroit : les permissions des fichiers Unix, où chaque chiffre contient les trois bits lecture-écriture-exécution du propriétaire, du groupe et des autres. chmod 755 signifie 111 101 101 : rwxr-xr-x, ce qu’affiche ls -l /bin/ls.

L’octal a aussi laissé un piège en C : un nombre qui commence par un zéro est octal. int a = 010; donne 8 à a. Python 3 et le mode strict de JavaScript refusent cette forme ambiguë et exigent 0o10.

Bits, quartets, octets et mots

  • Un bit est un chiffre binaire.
  • Un quartet (nibble) fait 4 bits : un chiffre hexadécimal.
  • Un octet (byte) fait 8 bits : deux chiffres hexadécimaux. C’est la plus petite unité de mémoire qui a sa propre adresse sur pratiquement toutes les machines actuelles. Il n’en a pas toujours été ainsi (certaines machines anciennes avaient des bytes de 6 ou 9 bits), c’est pourquoi les normes réseau anglophones disent octet quand elles veulent dire exactement 8 bits, et pourquoi le français dit octet tout court.
  • Un mot est la taille naturelle avec laquelle une machine calcule, en général la largeur de ses registres : 64 bits sur x86-64, ARM64 et RV64. Le terme est ambigu : pour des raisons de compatibilité, les manuels x86 appellent encore « mot » (word) 16 bits, « double mot » 32 bits et « quadruple mot » 64 bits, d’où les WORD PTR, DWORD PTR et QWORD PTR de l’assembleur.

L’ordre des octets d’un mot en mémoire est une autre question, traitée dans le chapitre sur le boutisme. La taille d’un kilooctet (1 000 ou 1 024 octets) est traitée dans le chapitre sur les unités.

Dans votre propre code

Tous les langages courants savent afficher et lire ces bases :

$ python3 -c "print(f'{2026:b} {2026:o} {2026:x} {2026:#x}')"
11111101010 3752 7ea 0x7ea
$ printf '%x %o %d\n' 2026 2026 0x7ea
7ea 3752 2026

En C, printf a %x et %o (et, depuis C23, %b) ; C23 a aussi normalisé le préfixe 0b des littéraux binaires, que les compilateurs acceptaient depuis longtemps comme extension.

À retenir

  • Dans un système positionnel de base b, chaque chiffre vaut b fois celui de droite. Les ordinateurs utilisent la base 2 parce que deux niveaux de tension se distinguent facilement et de façon fiable.
  • n bits donnent 2ⁿ motifs : 256 pour un octet, 65 536 pour 16 bits, environ 4,3 milliards pour 32 bits.
  • Décimal vers binaire : soustraire des puissances de deux, ou diviser par 2 et lire les restes de bas en haut. Binaire vers décimal : doubler et ajouter, bit par bit. 2026 = 11111101010₂.
  • Des fractions décimales comme 0,1 se répètent indéfiniment en binaire : on ne peut pas les stocker exactement.
  • L’hexadécimal est une abréviation du binaire : un chiffre hexadécimal = 4 bits (un quartet), deux = un octet. 2026 = 0x7EA. L’octal regroupe 3 bits et survit dans les permissions Unix (755) et dans le piège du zéro initial en C.
  • Un mot est la taille naturelle de la machine, 64 bits aujourd’hui, même si le x86 appelle encore « mot » 16 bits.

Fondamentaux

  1. F.1Niveaux d’abstraction et brève histoire des ordinateurs
  2. F.2Binaire et hexadécimal
  3. F.3Complément à deux et entiers signés
  4. F.4Virgule flottante (IEEE 754)
  5. F.5Caractères, ASCII et Unicode
  6. F.6Boutisme (endianness)
  7. F.7Parité, codes de Hamming et correction d’erreurs
  8. F.8Unités : kilo, kibi et compagnie