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
| Macro | Descrizione |
|---|---|
FE_DIVBYZERO | Divisione per zero |
FE_INEXACT | Risultato non rappresentabile esattamente |
FE_INVALID | Operazione matematica non valida |
FE_OVERFLOW | Overflow floating point |
FE_UNDERFLOW | Underflow floating point |
FE_ALL_EXCEPT | Tutte le eccezioni |
3️⃣ Funzioni principali
| Funzione | Descrizione |
|---|---|
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
| Macro | Significato |
|---|---|
FE_TONEAREST | Arrotondamento al più vicino (default) |
FE_DOWNWARD | Arrotondamento verso -∞ |
FE_UPWARD | Arrotondamento verso +∞ |
FE_TOWARDZERO | Arrotondamento 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>.
- Libreria
<cfenv> - Pragma
FENV_ACCESS - Eccezioni FE_*
- Modalità di arrotondamento
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
cfenvper verificare stabilità del risultato.