Causa della possibile perdita di precisione dei numeri a virgola mobile
I valori decimali a virgola mobile in genere non hanno una rappresentazione binaria esatta a causa del tipo di rappresentazione dei dati a virgola mobile da parte della CPU. Per questo motivo è possibile che si verifichi una perdita di precisione e che alcune operazioni a virgola mobile generino risultati imprevisti.
Questo risultato è la conseguenza di una delle seguenti possibili cause:
La rappresentazione binaria del numero decimale non è esatta.
I tipi di numeri utilizzati non corrispondono, ad esempio sono stati utilizzati sia valori di tipo float che double.
Per risolvere il problema, molti programmatori assicurano che il valore sia maggiore o minore del valore necessario oppure utilizzano una libreria BCD (Binary Coded Decimal) per garantire la precisione.
La rappresentazione binaria di valori a virgola mobile influisce sulla precisione e sull'accuratezza dei calcoli con virgola mobile. In Microsoft Visual C++ viene utilizzato il formato a virgola mobile IEEE.
Esempio
// Floating-point_number_precision.c
// Compile options needed: none. Value of c is printed with a decimal
// point precision of 10 and 6 (printf rounded value by default) to
// show the difference
#include <stdio.h>
#define EPSILON 0.0001 // Define your own tolerance
#define FLOAT_EQ(x,v) (((v - EPSILON) < x) && (x <( v + EPSILON)))
int main() {
float a, b, c;
a = 1.345f;
b = 1.123f;
c = a + b;
// if (FLOAT_EQ(c, 2.468)) // Remove comment for correct result
if (c == 2.468) // Comment this line for correct result
printf_s("They are equal.\n");
else
printf_s("They are not equal! The value of c is %13.10f "
"or %f",c,c);
}
Commenti
Per EPSILON è possibile utilizzare la costante FLT_EPSILON che per i valori float corrisponde a 1,192092896e-07F oppure la costante DBL_EPSILON che per i valori double corrisponde a 2,2204460492503131e-016. Per queste costanti è necessario includere float.h. Queste costanti sono definite come il più piccolo numero x positivo, in modo che x+1,0 non sia uguale a 1,0. Dal momento che si tratta di un numero molto piccolo, per i calcoli che comprendono numeri molto grandi è consigliabile utilizzare una tolleranza definita dall'utente.