Dela via


Varför Floating-Point tal kan förlora precision

Decimalvärden med flyttalstecken har vanligtvis ingen exakt binär representation. Det här är en bieffekt av hur processorn representerar flyttalsdata. För denna orsak kan du uppleva viss precisionsförlust, och vissa flyttalsoperationer kan ge oväntade resultat.

Det här beteendet är resultatet av något av följande:

  • Den binära representationen av decimaltalet kanske inte är exakt.

  • Det finns en typmatchningsfel mellan de tal som används (till exempel blandning av flyttal och dubbel).

För att lösa beteendet ser de flesta programmerare antingen till att värdet är större eller mindre än vad som behövs, eller så får de och använder ett binärkodat decimalbibliotek (BCD) som behåller precisionen.

Binär representation av flyttalsvärden påverkar precisionen och noggrannheten i flyttalsberäkningar. Microsoft Visual C++ använder IEEE-flyttalsformat.

Exempel

// 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

Kommentarer

För EPSILON kan du använda konstanterna FLT_EPSILON, som definieras för float som 1.192092896e-07F, eller DBL_EPSILON, som definieras för double som 2.2204460492503131e-016. Du måste inkludera float.h för dessa konstanter. Dessa konstanter definieras som det minsta positiva talet x, så att x+1.0 inte är lika med 1,0. Eftersom det här är ett mycket litet tal bör du använda användardefinierad tolerans för beräkningar med mycket stora tal.

Se även

Optimera din kod