Participer au site avec un Tip
Rechercher
 

Améliorations / Corrections

Vous avez des améliorations (ou des corrections) à proposer pour ce document : je vous remerçie par avance de m'en faire part, cela m'aide à améliorer le site.

Emplacement :

Description des améliorations :

Vous êtes un professionnel et vous avez besoin d'une formation ? Programmation avec
Le langage C
Voir le programme détaillé

Exceptions en virgule flottante

La librairie fenv.h Les directions d'arrondi


Entête à inclure

#include <fenv.h>  // <cfenv> en C++

Une exception en virgule flottante n'est pas forcément une exception au sens C++ ou Java. Dans le modèle de <fenv.h>, il s'agit d'un indicateur d'état qui peut être levé par un calcul : division par zéro, dépassement de capacité, résultat inexact, opération invalide...

Avant d'observer ces indicateurs, il est recommandé d'activer le pragma FENV_ACCESS. Sans lui, le compilateur peut réaliser des optimisations incompatibles avec l'observation fine de l'environnement flottant.

Type fexcept_t

Le type fexcept_t représente une sauvegarde des indicateurs d'exception. Il ne faut pas supposer qu'il s'agit d'un entier : son contenu est dépendant de l'implémentation et doit être produit par fegetexceptflag.

Macros d'exception

Macro Description
FE_ALL_EXCEPT Masque correspondant à toutes les exceptions supportées par l'implémentation.
FE_DIVBYZERO Division par zéro en virgule flottante.
FE_INEXACT Résultat inexact, par exemple après un arrondi nécessaire.
FE_INVALID Opération invalide, par exemple certaines opérations sur NaN ou racines carrées impossibles.
FE_OVERFLOW Dépassement de capacité par le haut.
FE_SNANS_ALWAYS_SIGNAL (C23) Macro optionnelle liée aux NaN signalants, fournie uniquement par certaines implémentations IEC 60559.
FE_UNDERFLOW Dépassement de capacité par le bas.

Fonctions associées

Fonction Rôle Depuis
int feclearexcept( int excepts ); Efface les indicateurs d'exception indiqués. C99
int fegetexceptflag( fexcept_t * flagp, int excepts ); Sauvegarde une représentation des indicateurs demandés. C99
int feraiseexcept( int excepts ); Lève explicitement les exceptions indiquées. C99
int fesetexcept( int excepts ); Positionne des indicateurs d'exception sans déclencher les effets associés à une vraie levée. C23
int fesetexceptflag( const fexcept_t * flagp, int excepts ); Restaure l'état des indicateurs à partir d'une valeur précédemment sauvegardée. C99
int fetestexcept( int excepts ); Teste les indicateurs actuellement levés. C99
int fetestexceptflag( const fexcept_t * flagp, int excepts ); Teste des indicateurs contenus dans une sauvegarde de type fexcept_t. C23

Exemple de code

Le programme suivant efface les indicateurs, provoque une division par zéro en virgule flottante, puis vérifie si l'indicateur correspondant a bien été levé.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
#include <fenv.h>
#include <stdio.h>

#pragma STDC FENV_ACCESS ON

int main() {

    volatile double zero = 0.0;

    feclearexcept( FE_ALL_EXCEPT );

    volatile double value = 1.0 / zero;
    (void) value;

    if ( fetestexcept( FE_DIVBYZERO ) ) {
        printf( "Division par zero detectee\n" );
    }

    return 0;
}
Détection d'une division par zéro

Une exécution possible produira le résultat suivant.

Division par zero detectee

Le bloc suivant montre comment sauvegarder un état d'exception avec fexcept_t, puis le restaurer ensuite.

 1 
 2 
 3 
 4 
 5 
 6 
 7 
 8 
 9 
 10 
 11 
 12 
 13 
 14 
 15 
 16 
 17 
 18 
 19 
 20 
 21 
 22 
#include <fenv.h>
#include <stdio.h>

#pragma STDC FENV_ACCESS ON

int main() {

    fexcept_t savedFlags;

    feclearexcept( FE_ALL_EXCEPT );
    feraiseexcept( FE_OVERFLOW );

    fegetexceptflag( &savedFlags, FE_OVERFLOW );

    feclearexcept( FE_ALL_EXCEPT );
    printf( "Apres effacement : %d\n", fetestexcept( FE_OVERFLOW ) != 0 );

    fesetexceptflag( &savedFlags, FE_OVERFLOW );
    printf( "Apres restauration : %d\n", fetestexcept( FE_OVERFLOW ) != 0 );

    return 0;
}
Sauvegarde et restauration d'indicateurs

Voici le résultat produit par ce second exemple.

Apres effacement : 0
Apres restauration : 1
Sur certains environnements Unix/Linux, l'édition des liens peut nécessiter l'option -lm, car les fonctions liées à l'environnement flottant peuvent être fournies avec la librairie mathématique.

Sujets connexes

Arrondis décimaux
Arrondis binaires
Environnement flottant
Pragmas de contrôle
Version de l'entête


La librairie fenv.h Les directions d'arrondi




Vous êtes un professionnel et vous avez besoin d'une formation ? Programmation avec
Le langage C
Voir le programme détaillé