P004 - Utrata precyzji w operacji dodawania liczb rzeczywistych
Program uruchomiono w środowisku Bloodshed Dev-C++ 4.9.9.2
// I Liceum Ogólnokształcące
// im. K. Brodzińskiego
// w Tarnowie
//--------------------------
// Koło informatyczne 2006/7
//--------------------------
// Program: P004
//--------------------------

#include <iostream>
#include <iomanip>

using namespace std;

main()
{
  float x = 0;

  cout.precision(0);     // 0 cyfr po przecinku
  cout.setf(ios::fixed); // format stałoprzecinkowy
  
  for(int i = 1; i <= 100000000; i++) x++;
  
  cout << x << endl << endl;
  
  system("pause");
}

 

Widok okienka konsoli w uruchomionym programie
16777216

       Wyjaśnienie

W kodzie zmiennoprzecinkowym mantysa m i wykładnik c rezerwują ustaloną ilość bitów. Zatem można dokładnie przedstawić tylko takie liczby, które da się wyrazić wzorem:

gdzie n jest liczbą bitów mantysy, a k liczbą co najwyżej n-bitową. Liczba bitów wchodzących do k określa tzw. precyzję zapisu zmiennoprzecinkowego, czyli ilość najbardziej znaczących cyfr, które są pamiętane dokładnie. Jeśli liczba wymaga do zapisu większej ilości bitów, to bity młodsze nie zostaną zapamiętane, co prowadzi właśnie do utraty precyzji.

W przypadku powyższego programu mantysa dla typu float jest 24-bitowa, czyli zapamiętuje dokładnie 24 bity liczby.  Liczbę 16777216 można zapamiętać jako:

Jeśli dodamy do tej liczby 1, to otrzymamy

16777217(10) = 1000000000000000000000001(2)

Jest to liczba 25-bitowa. Mantysa może natomiast zapamiętać tylko 24 najstarsze bity z pominięciem ostatniego bitu (zaznaczonego tutaj kolorem czerwonym).

Ponieważ licznik ułamka musi być liczbą całkowitą, to 0,5 zostaje odrzucone i otrzymujemy z powrotem liczbę 16777216. Dlatego wynik dodawania 1 zatrzymuje się na tej wartości, pomimo iż w pętli wykonywane jest 100 milionów dodawań.

 

Dokładny opis liczb rzeczywistych znajdziesz w artykule o binarnym kodowaniu liczb.

 

 


   I Liceum Ogólnokształcące   
im. Kazimierza Brodzińskiego
w Tarnowie

©2018 mgr Jerzy Wałaszek

Dokument ten rozpowszechniany jest zgodnie z zasadami licencji
GNU Free Documentation License.

Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl

W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe