# Mathématiques/Arithmétique flottante

Cette page est considérée comme une ébauche à compléter . Si vous possédez quelques connaissances sur le sujet, vous pouvez les partager en éditant dès à présent cette page (en cliquant sur le lien « »).
Ressources suggérées : Aucune (vous pouvez indiquer les ressources que vous suggérez qui pourraient aider d'autres personnes à compléter cette page dans le paramètre « ressources » du modèle engendrant ce cadre)

## Principe

Toute donnée contenue ou utilisée par un ordinateur est représentée par un nombre fini de bits. Chaque bit pouvant prendre deux valeurs, une donnée sur N bits pourra prendre 2$^N$ valeurs. Par ailleurs, suivant les processeurs et les langages utilisés, les types de données disponibles ont couramment une taille fixe, par exemple 32 bits, 64 bits ou plus, ce qui fait qu'ils peuvent prendre 2$^{32}$ valeurs, 2$^{64}$, etc. De ce fait, lorsqu'on essaye de travailler sur un ordinateur pour effectuer des calculs sur des nombres réels, on est limité par le fait qu'il n'est possible de représenter qu'une partie finie de $\mathbb {R}$. Cette discrétisation de $\mathbb {R}$ fait que le calcul numérique sur ordinateur est très différent du calcul mathématique qu'il est censé représenter.
Ainsi, les concepteurs de machines, comme de langages informatiques, doivent faire des choix dans la manière dont les nombres réels seront représentés et dans la manière dont ils seront manipulables. Ce livre montrera les problèmes qui se posent, par exemple pour gérer les situations où le résultat d'un calcul ne tombe pas exactement sur une des 2$^N$ valeurs, les problèmes liés aux infinis, aux opérations incorrectes (par ex. les divisions par zéro)... Les réponses à ces problèmes que trouvent les concepteurs de machines et de langages informatiques ont des impacts sur la manière dont un développeur pourra les utiliser pour créer des applications.
L'arithmétique des nombres réels sur ordinateur, dite en virgule flottante, est un domaine souvent peu maîtrisé, deux attitudes courantes étant soit de faire des calculs sans se soucier de ces questions, soit (après avoir buté sur une de ces questions sans savoir pourquoi) de se méfier des calculs numériques et de les éviter autant que possible. En effet, tout calcul peut comporter des erreurs d'arrondi ; et ces erreurs peuvent se propager et induire des résultats très largement inexacts. L'objectif de ce livre est de montrer au lecteur que les calculs en virgule flottante ne sont en rien mystérieux, et que les résultats de calcul qui peuvent sembler étranges ou aléatoires au premier abord sont en fait déterministes.

## Nombres flottants

Tout nombre réel peut s'écrire sous la forme $base*10^{exposant}$. Par exemple :
* $0,0014=14*10^{-4}=1,4*10^{-3}=0,14*10^{-2}$
* $10030=100,3*10^{2}=1,003*10^{4}=0,1003*10^{5}$
Cependant, chaque nombre peut s'écrire sous cette forme avec une infinité de couples $(base,exposant)$. Cette notation ne devient unique que si le premier chiffre significatif (non zéro) est placé avant la virgule, les autres étant placés après. Cette notation est alors dite scientifique. Par exemple :
* $0,0014=1,4*10^{-3}$
* $10030=1,003*10^{4}$
Le principe n'est pas limité à la base 10, et peut se généraliser pour toute base. La base 2 est la plus utilisée en informatique, mais ce paragraphe sera valable pour toute base ${b}$. Cette notation permet de représenter tout nombre réel non nul par un ensemble de trois valeurs :
* le signe du nombre,
* une mantisse contenant tous les chiffres de la forme normalisée,
* un exposant entier exprimant la puissance de ${b}$ par laquelle on multiplie la mantisse pour obtenir la valeur du nombre.
Le cas du nombre zéro est particulier, car il peut être représenté par une mantisse nulle et un exposant quelconque. Pour l'instant, nous considèrerons qu'on peut choisir arbitrairement pour la valeur zéro une des représentations possibles dans le format considéré. La représentation précise sera étudiée plus tard, nous étudierons d'abord le cas général des nombres non nuls.
Comme précisé en introduction, la représentation des nombres flottants que l'on étudie ici a une taille fixe. On peut choisir pour le signe une représentation de taille fixe, par exemple avec un chiffre qui sera à 0 pour les nombres positifs et à 1 pour les nombres négatifs. Il ne reste donc plus qu'à choisir le nombre de chiffres à attribuer à la mantisse (la précision, notée p) et à l'exposant (noté e). Si on suppose que l'on travaille en base 10, avec une précision de $p=4$ chiffres et un exposant pouvant varier entre $e_{min}=-2$ et $e_{max}=2$, nous pouvons représenter par exemple les nombres suivants :
* $1,000*10^{-2}=0,01$
* $5,075*10^{1}=50,75$
* $9,186*10^{2}=918,6$
On remarque que le plus petit nombre positif représentable dans ce format est 0,01, et le plus grand 999,9. On voit déjà une limite de l'arithmétique flottante : on ne peut représenter que des nombres dont la valeur absolue est entre $b^{e_{min}}$ et $\varrho ,\varrho ...\varrho *b^{e_{max}}$, où $\varrho$ est le plus grand chiffre (9 en décimal, 1 en binaire). Par ailleurs, si on manipule ces chiffres pour essayer de mieux « voir » comment ils sont (le lecteur est par ailleurs vivement encouragé à faire ou refaire ces manipulations lui-même), on peut remarquer qu'ils ne sont pas uniformément répartis entre ces deux bornes :
* $1,000*10^{-2}=0,01000$
* $1,001*10^{-2}=0,01001$
* $5,075*10^{1}=50,75$
* $5,076*10^{1}=50,76$
* $9,186*10^{2}=918,6$
* $9,187*10^{2}=918,7$
Ainsi, entre $b^{e_{min}}$ et $b^{e_{min}+1}$, les nombres représentés de cette manière sont espacés régulièrement de $b^{e_{min}-(p-1)}$, soit $10^{-5}$ dans cet exemple, puis, entre $b^{e_{min}+1}$ et $b^{e_{min}+2}$, l'écart vaut $b^{e_{min}-(p-1)+1}$, soit $10^{-4}$, pour aller jusqu'à $10^{-1}$ entre $b^{e_{max}}$ et $\varrho ,\varrho ...\varrho *b^{e_{max}}$. Ainsi, avoir une mantisse de taille fixe fait que les nombres flottants ne peuvent être répartis uniformément.
En notation binaire, qui est la plus utilisée par les ordinateurs, la mantisse commence toujours par le chiffre 1, sauf pour zéro. Ce chiffre peut donc être omis de la représentation en machine, ce qui permet de gagner un bit (mais ce qui laisse toujours en suspend le choix de la représentation du nombre zéro).

### Premiers calculs... et premières questions

Pour mieux comprendre l'effet de ces deux limitations (bornes et répartition des nombres flottants), on peut essayer de faire des calculs simples, comme des additions. Si on essaye d'additionner les deux plus petits nombres flottants représentables dans le format que nous avons choisi précédemment, on obtiendra :
$1,000*10^{-2}+1,001*10^{-2}=0,02001=2,001*10^{-2}$
Le résultat est représentable exactement dans le format considéré. Essayons maintenant d'additionner ce nombre et 50,75 :
$2,001*10^{-2}+5,075*10^{1}=50,77001=5,077001*10^{1}$
On constate que ce résultat ne peut être représenté exactement avec la précision fixée à 4 chiffres... Ainsi, même une simple addition peut ne pas être si évidente ! En pratique, le résultat devant être dans une précision à 4 chiffres, il faut l'arrondir. Ici, la valeur $5,077*10^{-1}$ est la plus proche, et pourraît être celle utilisée. Cependant, dans le cas suivant, le choix est moins simple:
$5,005*10^{1}+9,000*10^{2}=95,005=9,5005*10^{2}$
Ici, comment arrondir ? Doit-on choisir $9,500*10^{2}$ ou $9,501*10^{2}$ ? Et si le résultat avait été négatif ? Et dans le cas suivant :
$5,005*10^{1}+9,499*10^{2}=99,995=9,9995*10^{2}$
Doit-on choisir $9,999*10^{2}$, ou... ou quelle valeur, d'ailleurs ?
La question de l'arrondi a de multiples réponses. L'arrondi au plus proche laisse le choix pour le cas « 0,5 », qui peut être arrondi au supérieur ou à l'inférieur. Mais des arrondis « vers 0 » ou « vers l'infini » sont aussi parfois utilisés. Comme nous venons de le voir dans le dernier exemple, le choix de l'arrondi peut, dans les cas limites, faire qu'un résultat soit représentable ou non dans le format considéré.
Considérons maintenant la soustraction suivante :
$5,420*10^{1}-5,020*10^{1}=0,4=4,000*10^{-1}$
Là encore, le résultat tombe juste. Mais ce n'est pas toujours le cas...
$5,555*10^{-2}-5,554*10^{-2}=0,00001$
Cette fois-ci, le résultat tombe entre 0 et $b^{e_{min}}$, on ne peut donc le représenter de manière normalisée. On peut alors soit arrondir à $b^{e_{min}}$, et l'erreur relative serait assez grande ($1*10^{-2}$ au lieu de $1*10^{-5}$, l'erreur est d'un facteur 1000 !), soit à zéro. Mais, dans ce dernier cas, la différence de deux nombres exactement représentables dans ce format numérique serait nulle, et l'équivalence $x=y\Leftrightarrow x-y=0$ serait fausse !
Nous venons de voir qu'une représentation en virgule flottante des nombres réels posait un certain nombre de problèmes, notamment en terme d'arrondi des résultats et pour les valeurs trop grandes ou trop petites, et ce même sur des opérations simples. Nous avons pris l'addition et la soustraction comme premiers exemples, mais la multiplication, la division... sont soumises aux mêmes problèmes. Les chapitres suivants montreront comment chacun de ces problèmes peut trouver une solution, et comment un développeur peut les utiliser pour concevoir une application robuste.