Linguaggio C++

Libreria Cfenv

Introduzione alla libreria cfenv del C++: gestione dell’ambiente matematico floating point, modalità di arrotondamento, eccezioni numeriche e controllo dei calcoli.

La libreria <cfenv> permette di controllare il comportamento dell’unità di calcolo floating point del processore. È una libreria poco conosciuta, ma molto utile quando si richiedono calcoli precisi o quando bisogna gestire errori numerici come overflow, underflow, divisioni per zero o arrotondamenti.

La libreria fornisce strumenti per:

  • controllare le eccezioni matematiche (overflow, div-by-zero…)
  • modificare la modalità di arrotondamento
  • verificare se una certa eccezione si è attivata
  • resettare l’ambiente floating-point

1️⃣ Inclusione della libreria


#include <cfenv>
#pragma STDC FENV_ACCESS ON   // necessario per abilitare modifica FPU

La direttiva #pragma è richiesta dal C++ per assicurarsi che il compilatore non ottimizzi via le verifiche sulle eccezioni floating point.


2️⃣ Eccezioni gestibili

MacroDescrizione
FE_DIVBYZERODivisione per zero
FE_INEXACTRisultato non rappresentabile esattamente
FE_INVALIDOperazione matematica non valida
FE_OVERFLOWOverflow floating point
FE_UNDERFLOWUnderflow floating point
FE_ALL_EXCEPTTutte le eccezioni

3️⃣ Funzioni principali

FunzioneDescrizione
feclearexcept(mask)Azzera eccezioni
fegetexceptflag()Legge stato eccezioni
feraiseexcept(mask)Attiva artificialmente eccezioni
fetestexcept(mask)Testa se un’eccezione è avvenuta
fegetround()Legge modalità di arrotondamento
fesetround(mode)Imposta modalità di arrotondamento

4️⃣ Modalità di arrotondamento

MacroSignificato
FE_TONEARESTArrotondamento al più vicino (default)
FE_DOWNWARDArrotondamento verso -∞
FE_UPWARDArrotondamento verso +∞
FE_TOWARDZEROArrotondamento verso 0

5️⃣ Esempio: divisione per zero rilevata


#pragma STDC FENV_ACCESS ON
#include <cfenv>
#include <iostream>
using namespace std;

int main() {
    feclearexcept(FE_ALL_EXCEPT);

    double x = 1.0 / 0.0;

    if (fetestexcept(FE_DIVBYZERO)) {
        cout << "Divisione per zero rilevata!" << endl;
    }
}

6️⃣ Esempio: cambiare arrotondamento


fesetround(FE_DOWNWARD);
cout << rint(3.7) << endl;   // arrotonda verso -infinito → 3

7️⃣ Esempio: test underflow


feclearexcept(FE_ALL_EXCEPT);
double x = 1e-300 * 1e-300;

if (fetestexcept(FE_UNDERFLOW)) {
    cout << "Underflow rilevato" << endl;
}
LABORATORIO

Gestione delle Eccezioni Floating Point

In questo laboratorio imparerai a rilevare errori numerici come overflow, underflow, divisione per zero e arrotondamenti, utilizzando la libreria <cfenv>.


1 Divisione per zero

Realizza un programma che divide un numero per 0 e rileva l eccezione.


feclearexcept(FE_ALL_EXCEPT);
double x = 10.0 / 0.0;

if(fetestexcept(FE_DIVBYZERO))
    cout << "Errore: divisione per zero" << endl;

2 Overflow

Genera intenzionalmente un overflow floating point.


feclearexcept(FE_ALL_EXCEPT);
double x = 1e308 * 1e308;

if(fetestexcept(FE_OVERFLOW))
    cout << "Overflow!" << endl;

3 Modalità di arrotondamento

Cambia arrotondamento e osserva il risultato.


fesetround(FE_TOWARDZERO);
cout << rint(3.9) << endl;  // diventa 3

4 Esercizi

  • Testa tutte le eccezioni FE_ una per una.
  • Stampa il valore di fegetround() prima e dopo il cambio di modalità.
  • Crea una funzione che esegue un calcolo e restituisce quale eccezione è avvenuta.
  • Simula un algoritmo numerico e usa cfenv per verificare stabilità del risultato.