Reprezentacja danych numerycznych w komputerze

przez | 3 stycznia 2022

Wszystkie treści na stronie ir.migra.pl chronione są prawami autorskimi. Więcej informacji znajdziesz tutaj.

Uwaga: Zapoznaj się wcześniej z tematem A1 z podręcznika  „Teraz bajty. Informatyka dla szkół ponadpodstawowych. Zakres podstawowy. Klasa III” lub z tematami 50 i 51 z podręcznika „Informatyka 1-3. Podręcznik dla szkoły ponadpodstawowej. Zakres podstawowy”. Wykonaj zawarte w nim ćwiczenia i zadania.

Zapisy podstawy programowej 2024 realizowane w temacie:

I. Rozumienie, analizowanie i rozwiązywanie problemów.
Zakres rozszerzony. Uczeń spełnia wymagania określone dla zakresu podstawowego, a ponadto:
  1. przedstawia sposoby reprezentowania w komputerze znaków, liczb, wartości logicznych;

Spis treści

  1. Reprezentacja binarna liczb ujemnych
  2. Reprezentacja liczb niecałkowitych
    1. Reprezentacja stałopozycyjna liczb
    2. Reprezentacja zmiennopozycyjna liczb

1. Reprezentacja binarna liczb ujemnych

W temacie 50 z podręcznika „Informatyka 1-3. Podręcznik dla szkoły ponadpodstawowej. Zakres podstawowy” i temacie A1 z podręcznika „Teraz bajty. Informatyka dla szkół ponadpodstawowych. Zakres podstawowy. Klasa III”  wyjaśniliśmy, w jaki sposób zapisać dowolną liczbę naturalną w postaci dwójkowej (binarnej), zwanej naturalnym kodem binarnym (NKB).

Największą wartość liczby dziesiętnej (W10), jaką można zapisać na n bitach, można wyznaczyć ze wzoru:

W10 = 2n – 1,

np. na ośmiu bitach (n = 8) można zapisać maksymalną wartość w systemie dziesiętnym równą:

W10 = 28 – 1 = 256 – 1 = 255.

Aby wyznaczyć liczbę bitów n potrzebnych do zapisania wartości W w systemie dziesiętnym, należy przekształcić wzór W10 = 2n – 1.

2n = W10 – 1

n = log2 (W10 – 1)

Otrzymaną wartość n należy zaokrąglić w górę do najbliższej liczby naturalnej n (tzw. sufit).

Zapisanie w postaci dwójkowej liczby całkowitej ujemnej jest znacznie trudniejsze. Najbardziej oczywisty z matematycznego punktu widzenia sposób:

–147610 = –101110001002

jest, niestety, nieprzydatny, ponieważ w zapisie binarnym, stosowanym w komputerach, możemy posługiwać się tylko wartościami bitowymi: 0 i 1.

Aby rozwiązać ten problem, można przeznaczyć jeden bit liczby, np. najstarszy (najbardziej znaczący), na zapis znaku. Przyjmując, że na zapisanie liczby przeznaczamy 8 bitów, otrzymujemy np.:

Taka reprezentacja liczb ujemnych nie jest jednak najlepsza, choćby dlatego, że istnieją w niej dwie możliwości zapisania liczby 0:

000000002 = 0
100000002 = „–0”.

oraz suma liczb przeciwnych, w tym przypadku 30 + (-30),  na 8 bitach nie daje wszędzie wartości 0.

Sposób zapisu liczb ujemnych stosowany we wszystkich nowoczesnych komputerach wykorzystuje kod uzupełnieniowy do dwóch (U2). Wartość liczby a w kodzie uzupełnieniowym do dwóch (U2) wyraża się wzorem:

gdzie:

n – liczba bitów przeznaczonych do zapisania liczby,

a – liczba do zapisania w kodzie uzupełnieniowym (-2n-1 ≤ a < 2n-1),

aU2 – wartość liczby a w kodzie uzupełnieniowym do dwóch.

Liczbę aU2, uzyskaną za pomocą wzoru (1), rozwijamy do postaci dwójkowej.

Przykład 1. Wyznaczanie rozwinięcia dwójkowego liczby ujemnej w kodzie uzupełnieniowym do dwóch

a = –30, n = 8 (1 bajt)
aU2 = 28 + (–30) = 256 – 30 = 226 = 11100010 2

Jak wynika z przykładu, liczbę dwójkową 111000102 można interpretować jako 226 lub jako –30. Na pierwszy rzut oka wydaje się to sprzeczne ze zdrowym rozsądkiem.

Logiczna struktura procesora sprawia jednak, że taki zapis jest prawidłowy.

Na ośmiu bitach suma liczb przeciwnych, w tym przypadku -30 oraz 30, na każdej pozycji daje wartość 0.

– 3010  + 3010 = 11100010 U2 + 00011110 U2 = 1 00000000 U2

Dzięki takiemu sposobowi zapisu liczb całkowitych procesor nie musi mieć dwóch osobnych układów do operacji na liczbach nieujemnych i ujemnych, co upraszcza jego budowę. Warto przy tym zauważyć, że w kodzie uzupełnieniowym do dwóch znakowi liczby odpowiada najbardziej znaczący bit. Jeżeli jest on równy 1, to liczba jest ujemna, a jeżeli jest równy 0, to liczba jest nieujemna.

Ćwiczenie 1. Wyznaczamy rozwinięcie dwójkowe liczb ujemnych

Wyznacz rozwinięcia dwójkowe liczb: –100 (n = 8), –256 (n = 16), –1000 (n = 16) w kodzie uzupełnieniowym do dwóch (U2).

Przykład 2. Inny sposób wyznaczania reprezentacji ujemnej całkowitej w kodzie U2

Istnieje prostszy sposób wyznaczenia reprezentacji ujemnej całkowitej w kodzie U2 na podstawie binarnej reprezentacji liczby do niej przeciwnej.

Zadanie: Wyznacz w kodzie U2 rozwinięcie liczby a = – 68 na 8 bitach wraz z bitem znaku.
Dane: binarne rozwinięcie liczby naturalnej a wraz z bitem znaku równym 0.
Wynik: binarne rozwinięcie liczby przeciwnej -a wraz z bitem znaku w kodzie U2.

Przesuwając się od strony prawej do lewej, pozostawiamy wszystkie bity równe 0 i pierwszy bit równy 1, a każdy następny bit zamieniamy na przeciwny.

2. Reprezentacja liczb niecałkowitych

2.1. Reprezentacja stałopozycyjna liczb

Reprezentacja stałopozycyjna to reprezentacja, w której na część całkowitą liczby i na jej część ułamkową przeznacza się określoną liczbę bitów. Część całkowitą oraz część ułamkową traktuje się niezależnie. Znak liczby określa bit znaku (bz). Położenie przecinka oddzielającego część całkowitą od ułamkowej jest stałe.

W systemie pozycyjnym o podstawie p niecałkowita liczba dodatnia:

 (an-1 an-2 … a2 a1 a0 , a-1 a-2 … a-(m-1) a-m )p

ma wartość dziesiętną równą

an-1 ∙ pn-1 + an-2 ∙ pn-2 + … + a1 ∙ p1 + a0 ∙ p0 + a-1 ∙ p-1 + a-2 ∙ p-2 + … + a-(m-1) ∙ p-(m-1) + a-m ∙ p-m,

gdzie:

an-1 , an-2 , … , a1 , a0                          –             kolejne cyfry liczby przed przecinkiem,
a-1 , a-2 , … , a-(m-1) , a-m                     –             kolejne cyfry liczby po przecinku,
p                                                              –             podstawa systemu

Na przykład reprezentacją binarną stałopozycyjną liczby 13,625, na którą przeznaczymy po 6 bitów na część całkowitą oraz ułamkową (m = n = 6), będzie liczba:

0 001101 101000 U2.

Aby otrzymać binarne rozwinięcie wymiernej liczby ujemnej, można posłużyć się tym samym algorytmem co w przypadku liczb całkowitych (przykład 2.).

Aby obliczyć wartość binarnej liczby wymiernej w systemie dziesiętnym, możemy posłużyć się wzorem:

gdzie:
W10wartość liczby w systemie dziesiętnym,
bz bit znaku (bz Î {0, 1}),
n – liczba bitów części całkowitej,
m – liczba bitów części ułamkowej,
an-1 , an-2 , … , a1 , a0 kolejne bity liczby przed przecinkiem,
a-1 , a-2 , … , a-(m-1) , a-m kolejne bity liczby po przecinku.

Binarną reprezentacją stałopozycyjną liczby -13,625 będzie liczba:

1 110010 011000 U2.                              (bit znaku został pogrubiony)

Sprawdzimy poprawność wyznaczonej liczby, wykorzystując wzór [2.].

(-1) ∙ 1 ∙ 26 + 1 ∙ 21 + 1 ∙ 24 + 1 ∙ 25 + 1 ∙ 2-2 + 1 ∙ 2-3 = -64 + 50,375 = -13,625

Przykład 3. Zapis liczby 6,6875 w systemie dwójkowym – przykład liczby mającej skończone rozwinięcie binarne

Część ułamkowa liczby ma skończone rozwinięcie binarne, jeśli mianownik ułamka jest potęgą liczby 2. Będą to więc ułamki o mianownikach: 2, 4, 8, 16, 32, 64 … etc. Część całkowitą liczby dodatniej przedstawiamy w NKB (naturalnym kodzie binarnym). Ułamek przedstawiamy jako sumę ułamków o mianownikach będących potęgami liczby 2. Na początku musimy ustalić, na ilu bitach będziemy przechowywać liczbę, zarówno jej część całkowitą, jak i ułamkową. I tak liczba 610 = 1102, więc na jej reprezentację wystarczą 4 bity (łącznie z bitem znaku, w tym przypadku – 0, gdyż liczba jest dodatnia). Wartość 0, 687510 = 0,510 + 0,12510 + 0, 062510 = 1/2 10 + 0/410 + 1/8 10 + 1/1610. Zatem w części ułamkowej po przecinku będziemy mieć wartość 0, 1011. Ostatecznie otrzymamy:

(z zaznaczonym na szaro w obramowaniu bitem znaku liczby).

Aby znaleźć reprezentację liczby – 6, 6875, możemy postępować zgodnie z przykładem 2. Otrzymamy wówczas:

(z zaznaczonym na szaro w obramowaniu bitem znaku liczby).
Liczba, która w systemie dziesiętnym ma rozwinięcie skończone, w systemie dwójkowym może mieć rozwinięcie nieskończone.

Przykład 4. Nieskończone rozwinięcie binarne

W tabeli pokazujemy znajdowanie reprezentacji binarnej ułamka 0,4.

0,410 = 0,(0110)2 = 0,011001100110 … 2      

Ostateczna wartość reprezentacji ułamka mającego nieskończone rozwinięcie binarne zależy od liczby bitów przeznaczonych na reprezentację części ułamkowej oraz wartości dziesiętnego zaokrąglenia. Dla naszego przykładu przedstawia się to następująco:

Zaokrąglenie części ułamkowej odbywa się zgodnie z następującą zasadą: jeśli pierwszą niemieszczącą się cyfrą jest zero, to odrzucamy wszystkie niemieszczące się cyfry; w przeciwnym przypadku do ostatniej pozycji zaokrąglenia dodaje się 1.

Ćwiczenie 2. Obliczamy rozwinięcia dwójkowe liczb dziesiętnych

Oblicz rozwinięcia dwójkowe liczb: 0,25; 4,33; 8,0001.

2.2. Reprezentacja zmiennopozycyjna liczb

W wielu obliczeniach naukowych występują bardzo duże liczby, np.:

30! = 265252859812191000000000000000000.

W zapisie naukowym liczbę tę można zapisać w następujący sposób:

30! = 2,65253E32, tzn. 2,65253 · 1032.

W podobny sposób zapisujemy liczby bliskie zeru, np.:
stała grawitacyjna Gc = 0,0000000000667259 = 6,67259E-11, czyli 6,67259 · 10-11.
Dowolną liczbę rzeczywistą a można zapisać jako:

a = m · 10c,                                                                                     [3.]

gdzie:
m – mantysa liczby,
c – cecha liczby, c jest liczbą całkowitą.

Jeżeli mantysa m liczby a należy do przedziału lewostronnie domkniętego ❬0,1; 1), czyli

1 ≤ │m│ < 10                     (ogólnie  1 ≤ │m│ < p, gdzie p – podstawa systemu),

to mówimy o zapisie znormalizowanym.            

Ćwiczenie 3.

Zapisz w sposób znormalizowany następujące liczby: π, 10242, 1 000 000 000.

Im więcej cyfr w mantysie, tym dokładniej zapisana jest wartość liczby. Cyfry mantysy nazywamy cyframi znaczącymi.

W zapisie dwójkowym tę samą liczbę a można zapisać jako:

a = m · 2c,                           [4.]

gdzie:

2–1 │m│ < 20, czyli m ∈ ❬ 0,5; 1); c jest natomiast liczbą całkowitą.
1≤ │m│ < 2 m ∈ ❬ 1; 2)

Aby liczbę a zapisać w postaci bitowej, wystarczy przekształcić m i c do postaci binarnej i zapisać przy użyciu odpowiedniej liczby bitów. Dokładny sposób zapisu określa standard IEEE 754, definiujący dwa formaty:

  • pojedynczej precyzji – 1 bit na znak liczby, 8 bitów na cechę liczby powiększoną o 127 (tzw. bias), 23 bity na mantysę liczby, co pozwala na zapisanie liczb z przedziału ok. ❬-1038; 1038❭  z dokładnością do 8 znaczących cyfr dziesiętnych.
  • podwójnej precyzji – 1 bit na znak liczby, 11 bitów na cechę liczby powiększoną o 1023 (tzw. bias), 52 bity na mantysę liczby, co pozwala na zapisanie liczb z przedziału ok. ❬-10308, 10308❭ z dokładnością do 16 znaczących cyfr dziesiętnych.

Taki sposób zapisu liczb rzeczywistych nazywamy reprezentacją zmiennopozycyjną lub zapisem zmiennoprzecinkowym.

Liczbę w tym zapisie można więc wyrazić wzorem:

x = (-1)znak ∙ mantysa ∙ 2cecha-bias ,

gdzie:

znak – liczba 0 dla liczby dodatniej i 1 dla liczby ujemnej,

bias – wartość przesunięcia (ang. bias)  (127 dla liczb pojedynczej precyzji; 1023 dla liczb podwójnej precyzji).

Przykład 5. Obliczanie wartości dziesiętnej liczby zmiennoprzecinkowej  pojedynczej precyzji

Dana jest następująca liczba zmiennoprzecinkowa pojedynczej precyzji:

01000011101010000000000000000000 (IEEE 754). Obliczymy jej wartość dziesiętną.

a) Kod binarny dzielimy na poszczególne pola zawierające: znak liczby, cechę oraz bity mantysy.

b) Obliczamy wartość:

Ćwiczenie 4. Oblicz wartość dziesiętną liczby zmiennoprzecinkowej  pojedynczej precyzji 10111101010100000000000000000000.

Przykład 6. Zapisywanie liczby dziesiętnej jako liczby zmiennoprzecinkowej pojedynczej precyzji

Dana jest liczba 10,2510. Zapiszemy ją jako liczbę zmiennoprzecinkową pojedynczej precyzji

a) określamy bit znaku bz – będzie nim 0, gdyż liczba jest dodatnia,

b) przekształcamy liczbę do postaci iloczynu:

10,25 = 5,125 · 21 = 2,5625 · 22 = 1,28125 · 23

Część całkowita mantysy jest równa 1, a część ułamkowa jest równa  0,28125. Wartość cechy to 3.

c) Zamieniamy część ułamkową na liczbę binarną, czyli wyznaczamy mantysę w postaci binarnej:

0,28125 * 2 = 0,5625
0,5625 * 2 = 1, 125
0,125 * 2 = 0,25
0,25 * 2 = 0,50
0,50 * 2 = 1, 00                                                      Wynik zamiany mantysy:   0,2812510 = 010012

d) Łączymy elementy, pamiętając o tym, że wartość cechy należy powiększyć o tzw. bias (127):

e) Sprawdzamy:

Ćwiczenie 5.

Zapisz w standardzie IEEE 754 liczbę 12,75.

Zadania

  1. Na przykładzie liczby -23 przedstaw, w jaki sposób zapisuje się liczby ujemne w postaci binarnej.
  2. Na przykładzie liczby 4,35 przedstaw, w jaki sposób w systemie pozycyjnym o podstawie p zapisuje się liczbę a, mającą n cyfr przed przecinkiem i m cyfr po przecinku. Przyjmij, że p = 5.
  3. Wyjaśnij na wybranym przykładzie, na czym polega reprezentacja zmiennopozycyjna liczb rzeczywistych.
  4. Zapisz w standardzie IEEE 754 liczbę -13,625.
  5. Przedstaw algorytm zamiany ułamka dziesiętnego na liczbę dwójkową. Według tego algorytmu rozwiń dwójkowo liczbę 0,65.
  6. Dla zainteresowanych
  7. Napisz program wyznaczający postać binarną podanej liczby ze znakiem, przy wykorzystaniu podanej liczby bitów.