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.

 



List do administratora Serwisu Edukacyjnego Nauczycieli I LO

Twój email: (jeśli chcesz otrzymać odpowiedź)
Temat:
Uwaga: ← tutaj wpisz wyraz  ilo , inaczej list zostanie zignorowany

Poniżej wpisz swoje uwagi lub pytania dotyczące tego rozdziału (max. 2048 znaków).

Liczba znaków do wykorzystania: 2048

 

W związku z dużą liczbą listów do naszego serwisu edukacyjnego nie będziemy udzielać odpowiedzi na prośby rozwiązywania zadań, pisania programów zaliczeniowych, przesyłania materiałów czy też tłumaczenia zagadnień szeroko opisywanych w podręcznikach.



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

©2017 mgr Jerzy Wałaszek

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