précédent  index  suivant

11. Nombres en virgule flottante


11.1 J'ai un problème quand j'imprime un nombre réel.

Sur la plupart des architectures, les nombres réels (dits flottants) sont représentés en base 2, comme pour les entiers. Ainsi, le nombre 3.1 ne peut s'écrire exactement en base 2. La représentation binaire est un arrondi qui dépend de la précision du codage des flottants, et des choix du compilateur. De plus, avec une fonction comme printf(), le nombre à imprimer est converti en base 2 puis reconverti en base 10, ce qui augmente encore les imprécisions.

Il est préférable d'utiliser les double, qui ont une précision supérieure aux float, sauf si l'économie de mémoire est vraiment critique.

haut de page

11.2 Pourquoi mes extractions de racines carrées sont erronées ?

Assurez-vous d'avoir inclus math.h, d'avoir correctement déclaré les autres fonctions renvoyant des double. Une autre fonction de la bibliothèque standard avec laquelle il faut faire attention est atof(), dans stdlib.h.

haut de page

11.3 J'ai des erreurs de compilation avec des fonctions mathématiques

Il faut s'assurer d'avoir linké (lié) son code avec la bibliothèque mathématique. Par exemple, sous Unix, vous devez passer l'option -lm à la fin de la ligne de commande.

haut de page

11.4 Mes calculs flottants me donnent des résultats étranges et/ou différents selon les plateformes

Pour commencer, relisez 11.1. Si le problème est plus complexe, il convient de se rappeler que les ordinateurs utilisent des formats de représentation des flottants qui ne permettent pas des calculs exacts. Pertes de précision, accumulation d'erreurs et autres anomalies sont le lot commun du numéricien.

Rappelez-vous qu'aucun calcul sur des flottants n'a de chance d'être exact, en particulier, n'utilisez jamais == entre deux flottants. Ces problèmes ne sont pas spécifiques au C.

Dans certains problèmes, une solution peut être d'introduire un petit paramètre de relaxation, par exemple #define EPS 1e-10, puis de multiplier l'un des termes (judicieusement choisi) de vos calculs par (1 + EPS).

Pour plus de renseignements, on se reportera par exemple aux Numerical Recipes ou à Numerical Algorithms with C (cf. 3.9).

haut de page

11.5 Comment simuler == entre des flottants ?

Étant donné qu'il y a perte de précision très vite, pour comparer deux valeurs flottantes, on teste si elles sont assez proches. Plutôt que d'écrire une horreur du genre :

    double a, b;
    /* ... */
    if (a == b) /* HORREUR ! */
        /* ... */
    

on écrira :

    #include <math.h>
    /* ... */
    double a, b;
    /* ... */
    if (fabs (a - b) <= epsilon * fabs (a) )
        /* ... */
    

où l'on aura judicieusement choisi epsilon (non-nul !).

haut de page

11.6 Comment arrondir des flottants ?

La méthode la plus simple et la plus expéditive est (int)(x + 0.5). Cette technique ne fonctionne pas correctement pour les nombres négatifs aussi vaut-il mieux utiliser

    (int)(x < 0 ? x - 0.5 : x + 0.5)
    

haut de page

11.7 Pourquoi le C ne dispose-t-il pas d'un opérateur d'exponentiation ?

Parce que certains processeurs ne disposent pas d'une telle instruction. Il existe une fonction pow() déclarée dans math.h bien que la multiplication soit préférable pour de petits exposants.

haut de page

11.8 Comment obtenir Pi ?

Parfois une constante prédéfinie M_PI est déclarée dans math.h mais ce n'est pas standard aussi vaut-il mieux calculer pi soi-même via 4 * atan (1.0).

haut de page

11.9 Qu'est-ce qu'un NaN ?

« NaN is Not a Number », ce qui signifie « Ce n'est pas un nombre ». Un NaN est un nombre flottant qui est le résultat d'une opération non conforme, par exemple 0/0. Lorsqu'un NaN est produit, la plupart des architectures produisent une interruption (ou un signal) qui termine le programme, au moment de l'utilisation de celui-ci. Il est parfois possible de vérifier si un nombre est NaN. Un bon test est celui-ci :

    #define isNaN(x) ((x) != (x))
    

Certains compilateurs fournissent des facilités quant à la gestion des NaN. GCC fournit dans la bibliothèque mathématique (math.h) les fonctions isnan(), isinf() et finite().

haut de page

précédent  index  suivant

faq-fclc 5/3/2002 (8h 59:05)