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. Questo è un effetto collaterale del modo in cui la CPU rappresenta i dati a virgola mobile. Per questo motivo, è possibile che si verifichi una perdita di precisione e alcune operazioni a virgola mobile potrebbero produrre risultati imprevisti.

Questo comportamento è il risultato di uno dei seguenti:

  • La rappresentazione binaria del numero decimale potrebbe non essere esatta.

  • Esiste una mancata corrispondenza di tipo tra i numeri usati (ad esempio, combinazione di float e double).

Per risolvere il comportamento, la maggior parte dei programmatori garantisce che il valore sia maggiore o minore di quello necessario oppure ottiene e usa una libreria BCD (Binary Coded Decimal) che manterrà la precisione.

La rappresentazione binaria dei valori a virgola mobile influisce sulla precisione e l'accuratezza dei calcoli a virgola mobile. Microsoft Visual C++ usa 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);
}
They are not equal! The value of c is  2.4679999352 or 2.468000

Commenti

Per EPSILON, è possibile usare le costanti FLT_EPSILON, definite per float come 1.192092896e-07F o DBL_EPSILON, definite per double come 2.2204460492503131e-016. Per queste costanti è necessario includere float.h. Queste costanti sono definite come il numero positivo più piccolo x, in modo che x+1,0 non sia uguale a 1,0. Poiché si tratta di un numero molto ridotto, è consigliabile usare la tolleranza definita dall'utente per i calcoli che coinvolgono numeri molto grandi.

Vedi anche

Ottimizzazione del codice