Przepełnienie

Z Wikipedii, wolnej encyklopedii
Skocz do: nawigacja, szukaj

Przepełnienie, przepełnienie arytmetyczne (ang. overflow, arithmetic overflow) − sytuacja, w której wartość wyniku operacji arytmetycznej przekracza wielkość rejestru lub pamięci.

W większości komputerów rozróżniane są dwa warunki przepełnienia:

  • przeniesienie występujące podczas dodawania lub odejmowania, biorąc pod uwagę operandy i wyniki jako liczby bez znaku, nie może zostać w ostatecznym rozwiązaniu,
  • wynik ma znak inny niż możliwy do przewidzenia podczas operacji arytmetycznych, np. wynikiem dodawania dwóch liczb dodatnich jest liczba ujemna.

Podczas operacji wykorzystujących przeniesienie, dobrą praktyką jest sprawdzenie flagi przeniesienia (ang. carry flag) po zakończeniu dodawania lub odejmowania liczb całkowitych bez znaku, a w sytuacji, w której znak wyniku danej operacji arytmetycznej jest inny niż przewidywany − sprawdzenie flagi przepełnienia (ang. overflow flag).

Sposoby obsługi przepełnienia[edytuj | edytuj kod]

Istnieje kilka sposobów obsługi przepełnienia:

  1. Właściwy dobór typów liczb pod względem rozmiaru/długości i zapisu znaku podczas projektowania programu.
  2. Rozważny dobór kolejności wykonywania działań i wstępne sprawdzenie operandów, co uniemożliwia uzyskanie wyniku większego niż możliwy do przechowania.
  3. Przewidywanie sytuacji, w których może nastąpić przepełnienie i zapobieganie przepełnieniu przez dodanie do liczb dodatkowych bitów oraz interpretowanie części bitów jako bitów statusu.
  4. Przypisywanie wartości wskazujących na przepełnienie oraz zwrócenie flagi wartości.
  5. Ignorowanie przepełnienia.

Dzielenie przez zero nie jest traktowane jako przepełnienie arytmetyczne. W zbiorze liczb rzeczywistych dzielenie przez zero jest niezdefiniowane, a dla dzielenia \frac{0}{0} zdefiniowane wyniki to: plus nieskończoność albo minus nieskończoność w zależności od znaku, lub brak wyniku.

Przykłady przepełnienia[edytuj | edytuj kod]

Najczęściej używany typ całkowity w procesorach 32-bitowych pozwala zapisać wartości od -2^{31} (binarnie 10000000 00000000 00000000 00000000) do 2^{31}-1 (binarnie 01111111 11111111 11111111 11111111) i jest używany np. przez zmienną przechowującą liczbę sekund, które upłynęły od 1 stycznia 1970 00:00:00 UTC. Przepełnienie jest w tym przypadku przyczyną problemu roku 2038.

Zobacz też[edytuj | edytuj kod]