Udostępnij za pośrednictwem


Dlaczego liczby zmiennoprzecinkowe mogą tracić dokładność

Wartości dziesiętne zmiennoprzecinkowe zazwyczaj nie mają dokładnej reprezentacji binarnej. Jest to efekt uboczny tego, jak procesor reprezentuje dane zmiennoprzecinkowe. Z tego powodu może wystąpić utrata precyzji, a niektóre operacje zmiennoprzecinkowe mogą powodować nieoczekiwane wyniki.

To zachowanie jest wynikiem jednego z następujących:

  • Reprezentacja binarna liczby dziesiętnej może nie być dokładna.

  • Istnieje niezgodność typów między użytymi liczbami (na przykład mieszanie zmiennoprzecinkowych i podwójnych).

Aby rozwiązać ten problem, większość programistów zapewnia, że wartość jest większa lub mniejsza niż to, co jest potrzebne, albo pobierają i używają biblioteki binarnej kodowanej liczby dziesiętnej (BCD), która zachowa precyzję.

Binarna reprezentacja wartości zmiennoprzecinkowych wpływa na precyzję i dokładność obliczeń zmiennoprzecinkowych. Program Microsoft Visual C++ używa formatu zmiennoprzecinkowego IEEE.

Przykład

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

Komentarze

W przypadku pliku EPSILON można użyć stałych FLT_EPSILON, który jest zdefiniowany dla zmiennoprzecinkowych jako 1.192092896e-07F lub DBL_EPSILON, który jest zdefiniowany dla wartości podwójnej jako 2.2204460492503131e-016. Należy uwzględnić zmiennoprzecinkowe.h dla tych stałych. Te stałe są definiowane jako najmniejsza liczba dodatnia x, tak aby x+1.0 nie był równy 1.0. Ponieważ jest to bardzo mała liczba, należy stosować tolerancję zdefiniowaną przez użytkownika dla obliczeń obejmujących bardzo dużą liczbę.

Zobacz też

Optymalizacja kodu