Chapitre 316 minDébutant
Nombres à virgule en binaire : arrondi, précision, flottants
Par Josselyn C., prof de BTS SIO. Mis à jour le .
À la fin de ce chapitre, tu sauras
- convertir un nombre à virgule entre les bases 10, 2 et 16 ;
- reconnaître une écriture binaire infinie et périodique ;
- arrondir par défaut, par excès et au plus près, en base 10 et en base 2 ;
- expliquer les erreurs d'arrondi des flottants et les éviter dans un programme.
5 exercices corrigés1 schéma
Un nombre à virgule s'écrit en base 2 ou 16 comme en base 10 : les chiffres après la virgule ont pour poids les puissances négatives de la base, 2⁻¹ = 0,5, 2⁻² = 0,25, et ainsi de suite. Ce chapitre montre comment convertir un réel entre les bases 10, 2 et 16, pourquoi certains nombres simples comme 0,1 n'ont pas d'écriture binaire finie, comment arrondir en base 10 et en base 2, et ce que cela implique pour les calculs d'un ordinateur.
Les chiffres après la virgule
En base 10, 3,75 signifie 3 + 7 × 10⁻¹ + 5 × 10⁻² = 3 + 0,7 + 0,05. Les positions après la virgule sont numérotées −1, −2, −3… et leur poids est une puissance négative de la base.
C'est la même chose en base 2 :
| Position | 2 | 1 | 0 | , | −1 | −2 | −3 | −4 | −5 |
|---|---|---|---|---|---|---|---|---|---|
| Poids | 2² = 4 | 2¹ = 2 | 2⁰ = 1 | , | 2⁻¹ = 0,5 | 2⁻² = 0,25 | 2⁻³ = 0,125 | 2⁻⁴ = 0,0625 | 2⁻⁵ = 0,03125 |
Chaque poids après la virgule est la moitié du précédent. Retiens au moins les trois premiers : 0,5 ; 0,25 ; 0,125.
Du binaire vers le décimal
Tu additionnes les poids des bits à 1, des deux côtés de la virgule.
Exemple 1. (101,011)₂ = 4 + 1 + 0,25 + 0,125 = 5,375.
Exemple 2. (1101,101)₂ = 8 + 4 + 1 + 0,5 + 0,125 = 13,625.
Une autre façon de calculer, utile quand il y a beaucoup de bits après la virgule : la partie fractionnaire, lue comme un entier, divisée par 2 puissance le nombre de bits après la virgule. Pour (0,011)₂ : 011 vaut 3, il y a 3 bits, donc (0,011)₂ = 3 ÷ 2³ = 3 ÷ 8 = 0,375. Pour (0,11101)₂ : 11101 vaut 29, il y a 5 bits, donc 29 ÷ 32 = 0,90625.
Le sujet de l'E3 de la session 2026 commençait justement par un QCM de ce type : convertir (10110,11101)₂ en base 10. La partie entière vaut 22, la partie fractionnaire 0,90625 : le nombre vaut 22,90625 (proposition de corrigé).
De l'hexadécimal vers le décimal
Même principe avec les puissances de 16 : 16⁻¹ = 1/16 = 0,0625, 16⁻² = 1/256 ≈ 0,0039.
- (A,8)₁₆ = 10 + 8 × 1/16 = 10 + 0,5 = 10,5 ;
- (3,C)₁₆ = 3 + 12/16 = 3 + 0,75 = 3,75 ;
- (1F,2)₁₆ = 31 + 2/16 = 31 + 0,125 = 31,125.
Du décimal vers le binaire : les multiplications successives
On convertit séparément la partie entière (par les divisions successives du chapitre 2) et la partie fractionnaire, par des multiplications :
- multiplie la partie fractionnaire par 2 ;
- la partie entière du résultat (0 ou 1) est le bit suivant après la virgule ;
- garde la partie fractionnaire du résultat et recommence ;
- arrête-toi quand la partie fractionnaire vaut 0, ou quand tu as le nombre de bits demandé ;
- lis les bits de haut en bas : le premier obtenu est juste après la virgule.
Exemple : 5,8125. La partie entière 5 donne (101)₂. Pour 0,8125 :
0,8125 = (0,1101)₂, donc 5,8125 = (101,1101)₂.
Vérification : 4 + 1 + 0,5 + 0,25 + 0,0625 = 5,8125.
Quand la conversion ne s'arrête jamais
Convertis 0,1 :
| Calcul | Résultat | Bit |
|---|---|---|
| 0,1 × 2 | 0,2 | 0 |
| 0,2 × 2 | 0,4 | 0 |
| 0,4 × 2 | 0,8 | 0 |
| 0,8 × 2 | 1,6 | 1 |
| 0,6 × 2 | 1,2 | 1 |
| 0,2 × 2 | 0,4 | 0 |
| 0,4 × 2 | 0,8 | 0 |
| … | … | … |
À la sixième ligne, on retombe sur 0,2 : les calculs vont se répéter indéfiniment. 0,1 = (0,000110011001100110011…)₂, le motif 0011 se répète sans fin. On dit que l'écriture binaire de 0,1 est illimitée périodique, comme 1/3 = 0,333… en base 10.
Ça ne marche pas dans l'autre sens : tout nombre qui a une écriture binaire finie a aussi une écriture décimale finie, car 2⁻ⁿ = 5ⁿ ÷ 10ⁿ. Par exemple 2⁻³ = 0,125.
Du décimal vers l'hexadécimal
La méthode est la même en multipliant par 16 : la partie entière de chaque produit (de 0 à 15) donne un chiffre hexadécimal.
Exemple : 0,65.
| Calcul | Résultat | Chiffre |
|---|---|---|
| 0,65 × 16 | 10,4 | A |
| 0,4 × 16 | 6,4 | 6 |
| 0,4 × 16 | 6,4 | 6 |
0,65 = (0,A666…)₁₆ : le chiffre 6 se répète.
Le plus simple reste souvent de passer par le binaire et de regrouper par 4 bits, en partant de la virgule dans les deux sens : vers la gauche pour la partie entière, vers la droite pour la partie fractionnaire, en complétant par des 0 aux extrémités.
(1101,101)₂ → partie entière 1101, partie fractionnaire 1010 → (D,A)₁₆.
Vérification : (D,A)₁₆ = 13 + 10/16 = 13,625, et (1101,101)₂ = 13,625.
Arrondir un nombre : par défaut, par excès, au plus près
Arrondir, c'est remplacer un nombre par une valeur proche qui a moins de chiffres. Le programme demande trois façons de le faire, en base 10 et en base 2.
| Arrondi | Principe | 3,14159 au centième |
|---|---|---|
| Par défaut | La valeur juste en dessous : on supprime les chiffres en trop | 3,14 |
| Par excès | La valeur juste au-dessus | 3,15 |
| Au plus près | La plus proche des deux | 3,14, car 3,14159 est plus près de 3,14 que de 3,15 |
La règle de l'arrondi au plus près en base 10 : regarde le premier chiffre supprimé. S'il vaut 5 ou plus, arrondis par excès ; sinon, par défaut. 3,14159 au centième : le premier chiffre supprimé est 1, on arrondit par défaut à 3,14. 2,678 au centième : le premier chiffre supprimé est 8, on arrondit par excès à 2,68.
On arrondit aussi des entiers : 2 026 à la centaine près donne 2 000 par défaut, 2 100 par excès et 2 000 au plus près (le chiffre des dizaines, 2, est inférieur à 5).
En base 2, c'est encore plus simple, puisque le premier bit supprimé vaut 0 ou 1 : s'il vaut 1, on arrondit par excès ; s'il vaut 0, par défaut. Un 1 en première position supprimée représente en effet au moins la moitié de l'écart entre les deux arrondis possibles.
Exemple 1 : arrondir 45 = (101101)₂ à 8 = 2³ près.
- Par défaut : on remplace les 3 derniers bits par des 0 → (101000)₂ = 40.
- Par excès : on ajoute 1 au bit de poids 8 de la valeur par défaut → (110000)₂ = 48.
- Au plus près : le premier bit supprimé (poids 4) vaut 1 → par excès, 48. En effet, 45 est à 3 de 48 et à 5 de 40.
Exemple 2 : arrondir 0,1 à 8 bits après la virgule. 0,1 = (0,00011001 1001…)₂.
- Par défaut : (0,00011001)₂ = 25/256 = 0,09765625.
- Par excès : (0,00011010)₂ = 26/256 = 0,1015625.
- Au plus près : le 9e bit vaut 1 → par excès, (0,00011010)₂. On vérifie : 0,1015625 − 0,1 = 0,0015625, alors que 0,1 − 0,09765625 = 0,00234375.
Les chiffres significatifs
Les chiffres significatifs d'un nombre sont ses chiffres à partir du premier chiffre non nul, en lisant de gauche à droite. Ils mesurent la précision d'une valeur.
| Nombre | Chiffres significatifs | Combien |
|---|---|---|
| 2 026 | 2, 0, 2, 6 | 4 |
| 0,004 56 | 4, 5, 6 (les 0 de tête ne comptent pas) | 3 |
| 0,004 560 | 4, 5, 6, 0 (le 0 final indique une précision) | 4 |
| 1,20 × 10³ | 1, 2, 0 | 3 |
Pour se conformer à un nombre de chiffres significatifs, on arrondit au plus près au rang voulu. 12 345 avec 3 chiffres significatifs donne 12 300, qu'on écrit de préférence 1,23 × 10⁴ pour lever toute ambiguïté sur les 0. 0,076 54 avec 2 chiffres significatifs donne 0,077.
Les nombres à virgule dans un ordinateur
Un ordinateur stocke un nombre à virgule sur un nombre fixe de bits (32 ou 64), dans un format appelé virgule flottante. Le principe est celui de la notation scientifique, mais en base 2 : le nombre est écrit sous la forme ± 1,m × 2ᵉ, et on stocke le signe, l'exposant e et la mantisse m.
La norme IEEE 754 fixe ces formats. Le plus courant est la double précision sur 64 bits (le type float de Python, double en C# et en Java, Number en JavaScript) : 1 bit de signe, 11 bits d'exposant et 52 bits de mantisse. Cela donne environ 15 à 17 chiffres significatifs décimaux. La simple précision (32 bits : 1 + 8 + 23) en donne environ 7.
Comme la mantisse a un nombre fini de bits, un nombre comme 0,1, dont l'écriture binaire est infinie, est arrondi au plus près au moment où il est stocké. Python le montre si tu lui demandes plus de chiffres :
>>> f"{0.1:.20f}"
'0.10000000000000000555'
>>> 0.1 + 0.2
0.30000000000000004
>>> 0.1 + 0.2 == 0.3
False
0,1 et 0,2 sont stockés avec une petite erreur ; leur somme, arrondie à son tour, ne tombe pas sur la valeur stockée pour 0,3. Ce n'est pas un défaut de Python : C, Java, C# et JavaScript donnent exactement le même résultat, puisqu'ils suivent la même norme.
Exercices
Exercice 1 sur 5 Du binaire vers le décimal Réussi À revoir
Donne l'écriture décimale de chaque nombre.
- (11,11)₂
- (110,0101)₂
- (1001,1001)₂
- (0,0011)₂
Voir la réponseMasquer la réponse de l'exercice 1
- (11,11)₂ = 2 + 1 + 0,5 + 0,25 = 3,75.
- (110,0101)₂ = 4 + 2 + 0,25 + 0,0625 = 6,3125. Ou bien : 0101 vaut 5, sur 4 bits, donc 5/16 = 0,3125.
- (1001,1001)₂ = 9 + 9/16 = 9 + 0,5625 = 9,5625.
- (0,0011)₂ = 3/16 = 0,1875.
Tu avais trouvé ?
Exercice 2 sur 5 Du décimal vers le binaire Réussi À revoir
Convertis en binaire. Si l'écriture ne s'arrête pas, donne les 8 premiers bits après la virgule et repère le motif qui se répète.
- 0,375
- 12,75
- 0,2
- 6,3
Voir la réponseMasquer la réponse de l'exercice 2
- 0,375 × 2 = 0,75 → 0 ; 0,75 × 2 = 1,5 → 1 ; 0,5 × 2 = 1 → 1. 0,375 = (0,011)₂.
- 12 = (1100)₂ ; 0,75 × 2 = 1,5 → 1 ; 0,5 × 2 = 1 → 1. 12,75 = (1100,11)₂.
- 0,2 → 0,4 (0) → 0,8 (0) → 1,6 (1) → 1,2 (1) → 0,4 (0) → 0,8 (0) → 1,6 (1) → 1,2 (1)… 0,2 = (0,00110011…)₂, le motif 0011 se répète.
- 6 = (110)₂. 0,3 → 0,6 (0) → 1,2 (1) → 0,4 (0) → 0,8 (0) → 1,6 (1) → 1,2 (1) → 0,4 (0) → 0,8 (0)… 6,3 = (110,01001100…)₂ : après le premier 0, le motif 1001 se répète.
Tu avais trouvé ?
Exercice 3 sur 5 Réels et hexadécimal Réussi À revoir
- Convertis (2A,C)₁₆ en base 10.
- Convertis (10111,011)₂ en base 16, puis en base 10.
- Convertis 0,2 en base 16 (trois chiffres après la virgule).
Voir la réponseMasquer la réponse de l'exercice 3
- (2A,C)₁₆ = 2 × 16 + 10 + 12/16 = 42 + 0,75 = 42,75.
- Partie entière : 1 0111 → 0001 0111 → 17. Partie fractionnaire : 011 → 0110 → 6. (10111,011)₂ = (17,6)₁₆. En base 10 : 1 × 16 + 7 + 6/16 = 23 + 0,375 = 23,375. Vérification : (10111)₂ = 23 et (0,011)₂ = 0,375.
- 0,2 × 16 = 3,2 → 3 ; 0,2 × 16 = 3,2 → 3 ; et ainsi de suite. 0,2 = (0,333…)₁₆.
Tu avais trouvé ?
Exercice 4 sur 5 Arrondis Réussi À revoir
- Arrondis 7,384 6 au centième par défaut, par excès et au plus près.
- Écris 0,000 482 7 avec deux chiffres significatifs.
- Arrondis (10110111)₂ à 16 près (on garde les bits de poids 16 et plus) : par défaut, par excès, au plus près. Donne les résultats en binaire et en décimal.
- Arrondis (0,1011011)₂ à 2⁻⁴ près, au plus près. Donne le résultat en binaire et en décimal.
Voir la réponseMasquer la réponse de l'exercice 4
- Par défaut 7,38 ; par excès 7,39 ; au plus près 7,38, car le premier chiffre supprimé est 4.
- Les deux premiers chiffres significatifs sont 4 et 8 ; le suivant, 2, est inférieur à 5 : 0,000 48, soit 4,8 × 10⁻⁴.
- (10110111)₂ = 183. Par défaut : (10110000)₂ = 176. Par excès : (11000000)₂ = 192. Au plus près : le premier bit supprimé (poids 8) vaut 0 → par défaut, (10110000)₂ = 176. Vérification : 183 − 176 = 7 et 192 − 183 = 9.
- On garde 4 bits après la virgule : 0,1011 ; le 5e bit vaut 0 → par défaut. (0,1011)₂ = 11/16 = 0,6875. Vérification : (0,1011011)₂ = 91/128 ≈ 0,7109, plus proche de 0,6875 (écart 0,0234) que de 0,75 (écart 0,0391).
Tu avais trouvé ?
Exercice 5 sur 5 Le bug de la caisse Réussi À revoir
Un développeur écrit ce test pour valider le total d'un panier en Python :
total = 0.1 + 0.2
if total == 0.3:
print("Total correct")
else:
print("Erreur de total")
- Qu'affiche ce programme ? Explique pourquoi.
- Propose deux corrections.
Voir la réponseMasquer la réponse de l'exercice 5
- Il affiche « Erreur de total ». 0,1 et 0,2 n'ont pas d'écriture binaire finie : ils sont stockés arrondis sur 52 bits de mantisse, et leur somme vaut
0.30000000000000004, différente de la valeur stockée pour 0,3. - Deux corrections possibles :
- comparer avec une tolérance :
if math.isclose(total, 0.3):(aprèsimport math) ; - mieux, pour de l'argent, calculer exactement : en centimes avec des entiers (
10 + 20 == 30), ou avecDecimal("0.1") + Decimal("0.2") == Decimal("0.3"), qui vautTrue(aprèsfrom decimal import Decimal).
- comparer avec une tolérance :
Tu avais trouvé ?