Float

Z PHPEdia.pl
Skocz do: nawigacji, wyszukiwania

Float jest popularnym określeniem formatu liczb zmiennoprzecinkowych imitujących liczby rzeczywiste w arytmetyce komputerowej. W PHP typ ten ma długość 64 bitów (tzw. "podwójna precyzja" zgodnie ze standardem IEEE) oraz umożliwia zapisywanie zarówno liczb ujemnych, jak i dodatnich.

Pułapki obliczeń zmiennoprzecinkowych

Typowym błędem początkujących programistów jest utożsamianie liczb zmiennoprzecinkowych z liczbami rzeczywistymi, co najczęściej prowadzi do serii niezamierzonych pomyłek. Dokładność liczb zmiennoprzecinkowych jest ograniczona i wiele wzorów równoważnych z matematycznego punktu widzenia, w arytmetyce komputerowej prowadzi do uzyskania całkowicie odmiennych wyników.

Liczba zmiennoprzecinkowa zbudowana jest z czterech elementów:

  1. S - Znak
  2. B - Podstawa
  3. M - Mantysa
  4. E - Wykładnik

We współczesnych komputerach używa się wyłącznie liczb zmiennoprzecinkowych o podstawie 2, dlatego w pamięci zapisywane są tylko trzy elementy. Rzeczywista wartość liczby zmiennoprzecinkowej może być obliczona ze wzoru:

x = S * M * B^E

Mantysa przechowywana jest w postaci znormalizowanej, tj. reprezentuje wartość w zakresie [1, B[. Jeśli M jest stałe, a zmienia się wartość E, wówczas przesunięciu ulega przecinek, stąd nazwa całej reprezentacji.

Właściwości obliczeń na liczbach zmiennoprzecinkowych

  1. Arytmetyka zmiennoprzecinkowa nie jest łączna: (x + y) + z nie musi być równe x + (y + z)
  2. Arytmetyka zmiennoprzecinkowa nie jest przemienna: x (y + z) nie musi być równe xy + xz

Postać wzoru ma więc wpływ na końcowy wynik obliczeń.

Błędy zaokrągleń

Ponieważ ilość cyfr w wykładniku i mantysie jest z góry ustalona i skończona, prawie wszystkie wartości poza pewnym skończonym zbiorem reprezentowane są z mniejszym lub większym przybliżeniem. Typ podwójnej precyzji potrafi zachować w odpowiednich warunkach sensowną dokładność nawet do 16 miejsc po przecinku, lecz dalej nie ma co na to liczyć. Ponadto problemy pojawiają się nie tylko przy bardzo małych ułamkach. Niektóre elementarne ułamki o skończonym rozwinięciu w systemie dziesiętnym, po przekształceniu na zapis binarny będą mieć rozwinięcie nieskończone, co oznacza, że nie da się ich przedstawić dokładnie. Takimi liczbami są np. wartości 0.1 i 0.7. Jeśli chcesz zmniejszyć ilość błędów, staraj się w miarę możliwości używać ułamków będących potęgami dwójki, np. 0.5 czy 0.125.

Porównywanie

Liczb zmiennoprzecinkowych nie powinno porównywać się operatorem == ze względu na możliwe błędy zaokrągleń. Zamiast tego, możemy wykorzystać następującą formułę:

abs($liczba1 - $liczba2) < 0.0000000000001

Liczba po prawej, tzw. epsilon niekoniecznie musi mieć dokładnie taki kształt. Określa ona rozbieżność, jaką jesteśmy w stanie zaakceptować.