Écriture d’un nombre flottant

1) introduction

Nous avons vu comment sont représentés les entiers relatifs au sein d’un ordinateur. Nous allons maintenant voir comment sont représentés les nombres réels, appelés ici nombres flottants.

2) représentation de la partie décimale d’un nombre

a) base 10 vers base 2

Partons tout de suite sur un exemple : comment représenter 5,1875 en binaire ?

Il nous faut déjà représenter 5, ça, pas de problème : 101

Comment représenter le “,1875” ?

On obtient à une suite de “a + 0,b” (“0 + 0,375”, “0 + 0,75”, “1 + 0,5” et “1 + 0,0”). Il suffit maintenant de “prendre” tous les “a” (dans l’ordre de leur obtention) afin d’obtenir la partie décimale de notre nombre : 0011

Nous avons 101,00112 qui est la représentation binaire de 5,187510

Exercice 1

Trouvez la représentation binaire de 4,12510

Exercice 2

Trouvez la représentation binaire de 0,2510

Exercice 3

Trouvez la représentation binaire d’un tiers 1/3 (attention ne pas arrondir à 0,33 par exemple)

b) base 2 vers base 10

Il est possible de retrouver une représentation décimale en base 10 à partir d’une représentation en binaire.

Partons de 100,01012

Pas de problème pour la partie entière, nous obtenons “4”.

Pour la partie décimale nous devons écrire : 0 x 2-1 + 1 x 2-2 + 0 x 2-3 + 1 x 2-4 = 0,3125.

Nous avons donc 4,312510

Exercice 4

Trouvez la représentation décimale de 100,0012

Exercice 5

Trouvez la représentation décimale de 1,1012

c) le cas particulier de 0,110

Intéressons-nous à la conversion de 0,110.

0,1 x 2 = 0,2 = 0 + 0,2

0,2 x 2 = 0,4 = 0 + 0,4

0,4 x 2 = 0,8 = 0 + 0,8

0,8 x 2 = 1,6 = 1 + 0,6

0,6 x 2 = 1,2 = 1 + 0,2

0,2 x 2 = 0,4 = 0 + 0,4

Nous constatons que la 6e ligne est identique à la 2e ligne. Le processus va donc se poursuivre sans jamais s’arrêter, car après le 0,2 x 2 = 0,4 = 0 + 0,4 nous allons retrouver :

0,4 x 2 = 0,8 = 0 + 0,8

0,8 x 2 = 1,6 = 1 + 0,6

0,6 x 2 = 1,2 = 1 + 0,2

et nous retombons donc sur 0,2 x 2 = 0,4 = 0 + 0,4…

le processus de conversion ne s’arrête jamais, nous obtenons : 0,0001100110011…, le schéma “0011” se répète à l’infini. Cette caractéristique est très importante, nous aurons l’occasion de revenir là-dessus plus tard.

d) écrire un nombre binaire à l’aide de puissance de 2

En base dix, il est possible d’écrire les très grands nombres et les très petits nombres grâce aux puissances de dix (exemples 6,02.1023 ou 6,67.10-11). Il est possible de faire exactement la même chose avec une représentation binaire, puisque nous sommes en base 2, nous utiliserons des puissances de deux à la place des puissances dix (exemple : 101,1101.210).

Pour passer d’une écriture sans “puissance de deux” à une écriture avec “puissance de deux”, il suffit de décaler la virgule :

1101,1001 = 1,1011001.211

pour passer de 1101,1001 à 1,1011001 nous avons décalé la virgule de 3 rangs vers la gauche d’où le 211 (attention de ne pas oublier que nous travaillons en base 2 le 11 correspond bien à un décalage de 3 rangs de la virgule).

Si l’on désire décaler la virgule vers la droite, il va être nécessaire d’utiliser des “puissances de deux négatives”

0,0110 = 1,10.2-10

nous décalons la virgule de 2 rangs vers la droite, d’où le -10

3) représentation des flottants dans un ordinateur

a) principe

La norme IEEE 754 est la norme la plus employée pour la représentation des nombres à virgule flottante dans le domaine informatique. La première version de cette norme date de 1985.

Nous allons étudier deux formats associés à cette norme : le format dit “simple précision” et le format dit “double précision”. Le format “simple précision” utilise 32 bits pour écrire un nombre flottant alors que le format “double précision” utilise 64 bits. Dans la suite nous travaillerons principalement sur le format 32 bits.

Que cela soit en simple précision ou en double précision, la norme IEEE754 utilise :

image

Pour écrire un nombre flottant en respectant la norme IEEE754, il est nécessaire de commencer par écrire le nombre sous la forme 1,xxxxxx.2y (avec y l’exposant), il faut obligatoirement qu’il y ait un seul chiffre à gauche de la virgule et il faut que ce chiffre soit un 1.

Par exemple le nombre 1010,11001 devra être écrit 1,01011001.211. Autre exemple, 0,00001001 devra être écrit 1,001.2-101.

La partie xxxxxx de 1,xxxxxx.2y constitue la mantisse (dans notre exemple 1010,11001 la mantisse est 01011001).

b) problème de l’arrondi

Revenons au cas de 0,110 :

Nous avons vu plus que la représentation en binaire est infinie :

0,0001100110011…2, le schéma “0011” se répète à “l’infini”

La mémoire d’un ordinateur n’étant pas infinie, nous allons devoir nous limiter à 32 bits (en simple précision) ou à 64 bits (en double précision) pour la représentation de 0,110

Nous obtenons donc la représentation suivante (simple précision) :

0,110 => 00111101110011001100110011001100

Si nous procédons à la conversion inverse (conversion en base 10 du nombre flottant ci-dessus) nous n’obtenons pas 0,1 mais 0,099999994 !

Cette légère erreur était prévisible, elle est due à la limitation imposée (32 bits dans cet exemple).

Cette représentation avec un nombre limité de bits des nombres flottants est un problème classique en informatique. Cela peut entraîner des erreurs d’arrondi dans les calculs qui peuvent être très gênants si on n’y prend pas garde. Il faut donc être très méfiant quand on utilise des flottants pour des calculs.

Prenons un exemple simple :

a = 0.1
b = 0.2
c = a + b
if c == 0.3:
	print("pas de problème")
else :
	print("oups...??!")

Le résultat attendu après l’exécution de ce programme peut paraître évident : nous devrions voir s’afficher le message “pas de problème”…pourtant c’est le message “oups…??!” qui s’affiche !

Comme nous l’avons vu, la représentation de 0.1 en mémoire pose un problème, le résultat du calcul a + b pose donc aussi un problème (nous n’obtenons pas exactement 0.3), donc c == 0.3 renvoie False

On évitera donc de procéder à des comparaisons de flottants dans les programmes.