Les flottants sont des représentations en mémoire d'une partie des
nombres rationnels ; il est évidemment impossible de représenter des
nombres réels quelconques, pour des raisons de cardinalité. Seuls les
rationnels dont la forme irréductible est , peuvent avoir une
représentation exacte ; les autres ont nécessairement une représentation
approchée (par exemple, le nombre décimal
a
comme représentation en base 2, la
partie soulignée étant répétée indéfiniment). Cette représentation fait
l'objet de la norme IEEE 754, proposée par William Kahan (Turing
Award 1989), publiée en 1985 et adoptée par la plupart des fabricants
d'ordinateurs (Cray étant une exception notable). Cette norme distingue
deux niveaux de précision : simple (sur 4 octets) et double (sur 8
octets).
Prenons l'exemple des flottants en simple précision ; les 32 bits
sont répartis en :
Dans l'exposant, soustraire 127 permettrait de représenter le plus petit
exposant, , par les bits 0000 0000 et le plus grand
exposant,
, par les bits 1111 1111 ;
est par
exemple représenté par 0111 1111. En fait, 0000 0000
et 1111 1111 ont des significations spéciales, pour représenter
0,
, et NaN (c'est-à-dire Not a Number) ; les
exposants extrêmes des flottants normalisés sont donc
(par
0000 0001) et
(par 1111 1110).
La valeur de la mantisse étant toujours , zéro n'est pas
représentable dans ce schéma ; par convention, le bit de signe suivi de
31 bits nuls représentent la valeur
(et non
). Il y aurait alors un << trou >> entre 0 et le
plus petit nombre normalisé, qui a comme bits d'exposant 0000
0001 et les bits de mantisse nuls. Pour combler ce trou, on convient
que si les 8 bits d'exposant sont nuls, la valeur est un flottant
dénormalisé, de valeur
.
Si les bits d'exposant valent 1, et les bits de mantisse valent
0, la valeur est , qui est obtenue dans le cas
d'une division par 0. Enfin, si les bits d'exposant valent 1,
et les bits de mantisse ne sont pas tous nuls, la valeur est NaN,
qui peut être obtenue comme le résultat d'opérations illicites, comme
,
, ou
.
Bien que portant les mêmes noms (addition, multiplication), les
opérations flottantes ne sont pas ces opérations mathématiques, et n'ont
pas les mêmes propriétés. Par exemple, l'addition n'est pas associative
: on peut vérifier que
, tandis
que
. Autre exemple : la série
converge !
Il est souhaitable que le numéricien programmeur ait une idée de l'implémentation des flottants, sans qu'il doive nécessairement en connaître tous les détails. Il y a en C++ plusieurs niveaux de précision, qui caractérisent différents types flottants : float (sur 4 octets), double (sur 8) et long double (sur 8 ou 16). Diverses constantes sont définies dans cfloat :
FLT_EPSILON
: le plus petit FLT_MIN
et FLT_MAX
, le plus petit et le plus grand
floatDBL_EPSILON
, DBL_MIN
et
DBL_MAX
pour le type double.
On ne testera jamais l'égalité de deux flottants avec == ou != ; il est préférable de tester un écart relatif :
if (fabs(x-y) < epsilon * x) { ... }
Les valeurs de type double peuvent être notées avec un signe, un point décimal et un exposant optionnel. Pour le type float, la constante doit être terminée par f :
const double pi = 3.141592653; const float avogadro = 6.02e23f;
Certaines constantes mathématiques sont définies dans <cmath>,
en particulier par M_PI.
Un nombre flottant peut être lu sur l'entrée standard (le clavier) cin
au moyen de l'opérateur >>
, et écrit sur la sortie standard
(l'écran) cout au moyen de l'opérateur <<
:
double x; cin >> x; cout << x;
La précision peut être indiquée de la façon suivante (ici, 15 chiffres significatifs, sinon 6 chiffres par défaut) :
cout.precision(15); cout << x;
Le format scientifique (pour obtenir, par exemple, 1.5421e-3) le format fixe, et le format par défaut peuvent être spécifiés de la façon suivante :
cout.setf(ios::scientific, ios::floatfield); cout << "format scientifique : " << x; cout.setf(ios::fixed, ios::floatfield); cout << "format fixe : " << x; cout.setf(0,ios::floatfield); cout << "format par défaut : " << x;