Zapis zmiennoprzecinkowy, kody binarne



Niezbędne podstawy


Odrobina matematyki jako słowo wstępu


Żeby móc mówić o liczbach zmiennoprzecinkowych należy zrozumieć czym są liczby wymierne. Liczba wymierna to liczba, którą można przedstawić w postaci ułamka zwykłego. Dla przypomnienia to ten ułamek z kreską poziomą, który ma licznik i mianownik. Przykładem ułamka zwykłego jest ½.

Ułamki mają jeszcze postać dziesiętną. Przykładem ułamka dziesiętnego jest 0,5.

Niektóre ułamki zwykłe nie mają skończonej reprezentacji jako ułamek dziesiętny. Na przykład ułamek ⅓ zapisany dziesiętnie ma postać 0,(3). Taka notacja oznacza, że ułamek dziesiętny ma rozwinięcie okresowe. Zawartość nawiasu powtarzana jest w nieskończoność 0,33333.... Okres ułamka może mieć kilka cyfr, na przykład 0,38(12). Taki okres rozwija się do ułamka 0,3812121212....

Liczby wymierne zapisywane binarnie

Liczby wymierne można zapisać także binarnie. Algorytm na zamianę liczb całkowitych z postaci dziesiętnej na postać binarną opisałem w artykule na temat systemu binarnego. Do zamiany zostaje część po przecinku. Weźmy na przykład liczbę 0,25. Aby zapisać ją binarnie należy postępować zgodnie z algorytmem:

  1. Zapisz 0,,
  2. Pomnóż ułamek przez 2, jeśli wynik jest większy bądź równy 1 należy dopisać 1 w reprezentacji binarnej. W przeciwnym wypadku należy dopisać 0.
  3. Jeśli wynik jest równy 1 jest to koniec algorytmu. Jeśli wynik jest mniejszy od 1 należy przejść do punktu drugiego. Jeśli wynik jest większy od 1 należy odjąć od niego 1 i przejść do punktu drugiego.

Mam nadzieję, że przykład pozwoli Ci lepiej zrozumieć zasadę działania algorytmu. Zacznijmy od liczby 0,75.

  1. Postać binarna 0,,
  2. 0,75 * 2 = 1,5. Wynik jest większy od 1 więc dopisuję 1. Postać binarna 0,1. Wynik jest większy od 1 więc odejmuję jedynkę: 1,5 - 1 = 0,5,
  3. 0,5 * 2 = 1. Wynik jest równy 1 więc dopisuję 1. Postać binarna 0,11. Wynik jest równy 1 więc to koniec algorytmu,
  4. 0,75 zapisane jako ułamek binarny to 0,11.

Inny przykład, tym razem ułamek dziesiętny to 0,125:

  1. Postać binarna 0,,
  2. 0,125 * 2 = 0,25. 0,25 < 1 więc dopisuję 0. Postać binarna to 0,0,
  3. 0,25 * 2 = 0,5. 0,5 < 1 więc dopisuję 0. Postać binarna to 0,00,
  4. 0,5 * 2 = 1. 1 == 1 więc dopisuję 1. Postać binarna to 0,001, koniec algorytmu,
  5. 0,125 zapisane jako ułamek binarny to 0,001.

Nie wszystkie ułamki, które mają skończone rozwinięcie dziesiętne są skończone w postaci binarnej. Spójrz jak wygląda to w przypadku ułamka 0,1:

  1. Postać binarna 0,,
  2. 0,1 * 2 = 0,2. 0,2 < 1 więc dopisuję 0. Postać binarna to 0,0,
  3. 0,2 * 2 = 0,4. 0,4 < 1 więc dopisuję 0. Postać binarna to 0,00,
  4. 0,4 * 2 = 0,8. 0,8 < 1 więc dopisuję 0. Postać binarna to 0,000,
  5. 0,8 * 2 = 1,6. 1,6 > 1 więc dopisuję 1 i odejmuję 1 od wyniku. Postać binarna to 0,0001,
  6. 0,6 * 2 = 1,2. 1,2 > 1 więc dopisuję 1 i odejmuję 1 od wyniku. Postać binarna to 0,00011,
  7. Ułamek 0,2 występował już w kroku 3. Jeśli liczba się powtarza mamy do czynienia z ułamkiem, który ma nieskończone rozwinięcie binarne. Postać binarna to 0,0(0011).

Aby zapisać liczbę wymierną, która ma zarówno część całkowitą i ułamkową należy połączyć zapis części całkowitej i ułamkowej. Na przykład liczba 20,1 zapisana binarnie to 10100,0(0011). Jest to tak zwana stałoprzecinkowa reprezentacja liczby wymiernej.

Notacja naukowa a liczby wymierne

W matematyce poza standardowym zapisem liczb, który już znasz 10, 123,15 czy 0,00000827194 istnieje tak zwana notacja naukowa. Jest ona pomocna przy zapisywaniu bardzo dużych/małych liczb w stosunkowo zwięzłej formie. Na przykład liczbę 0,00000827194 można zapisać jako \(8,27194 * 10^{-6}\). Inna postać tej liczby to 8,27194e-6.

W języku Java możesz zobaczyć jak dana liczba wygląda w postaci naukowej:

System.out.println(String.format("%e", 123.456));

Po uruchomieniu powyższego kodu na konsoli pokaże się:

1.234560e+02


 

Obliczanie wartości liczby zmiennoprzecinkowej

Z liczbami zmiennoprzecinkowymi (ang. floating point numbers) spotkaliście się już zapewne na zajęciach z fizyki. Otóż zapis dużych liczb (lub bardzo małych) w normalnej notacji pozycyjnej jest niewygodny, gdyż wymaga sporej ilości cyfr. Dlatego  liczby takie zapisuje się w sposób następujący:

 

3,25 × 1033

Zapis składa się z trzech liczb:

 

m - mantysy, u nas równej 3,25
p - podstawy systemu, u nas równej 10
c - cechy, u nas równej 33

 

Wartość liczby zmiennoprzecinkowej obliczamy zgodnie ze wzorem:

 

L = m × pc

 

Wzór pozwala obliczyć wartość liczby zmiennoprzecinkowej zapisanej w dowolnym systemie pozycyjnym, a nie tylko dziesiętnym.

 

Przykład:

Obliczyć wartość zmiennoprzecinkowej liczby trójkowej 2,21 × 1021(3).

Najpierw obliczamy wartości poszczególnych składników liczby zmiennoprzecinkowej pamiętając, iż każdy z nich jest zapisany w systemie trójkowym:

 

m = 2,21(3) = 2 × 30 + 2 × 3-1 + 1 × 3-2 = 2 × 1 + 2 × 1/3 + 1 × 1/9 = 2 + 2/3 + 1/9 = 2 7/9

p = 10(3) = 1 × 31 + 0 × 30 = 3

c = 21(3) = 2 × 31 + 1 × 30 = 2 × 3 + 1 × 1 = 6 + 1 = 7

 

Teraz wykorzystujemy podany wzór do wyznaczenia wartości dziesiętnej tej liczby:

 

L = m × pc = 2 7/9 × 37 = 25/9 × 37 = 25 × 35 = 25 × 243 = 6075

 

Obliczyć wartość zmiennoprzecinkowej liczby szesnastkowej A,CB × 10D.

 

m = A,CB(16) = A × 160 + C × 16-1 + B × 16-2
m = A,CB(16) = 10 × 160 + 12 × 16-1 + 11 × 16-2
m = A,CB(16) = 10 × 1 + 12 × 1/16 + 11 × 1/256
m = A,CB(16) = 10 + 12/16 + 11/256
m = A,CB(16) = 10 + 192/256 + 11/256
m = A,CB(16) = 10 203/256

p = 10(16) = 1 × 161 + 0 × 160 = 16

c = D(16) = D × 160 = 13 × 160 = 13

L = m × pc = 10 203/256 × 1613 = 2763/256 × 1613 = 2763 × 1611 = 2763 × 17592186044416

L = 48607210040721408

 

Postać znormalizowana liczby zmiennoprzecinkowej

Zapis zmiennoprzecinkowy - skąd wzięła się nazwa tego sposobu zapisu liczb? Otóż położenie przecinka w mantysie nie jest ustalone i może się dowolnie zmieniać. Poniższe zapisy oznaczają tę samą liczbę:

 

325 × 1020 = 32,5 × 1021 = 3,25 × 1022 = 0,325 × 1023 = 0,0325 × 1024, itd.

 

Oczywiście zmiana położenia przecinka w mantysie wpływa na wartość cechy liczby. Reguła jest bardzo prosta i obowiązuje we wszystkich systemach pozycyjnych (dlaczego?):

 

Przesunięcie przecinka o 1 pozycję w lewo wymaga zwiększenia cechy o 1.

Przesunięcie przecinka o 1 pozycję w prawo wymaga zmniejszenia cechy o 1.

 

Postaraj się uzasadnić te reguły dla dowolnego systemu pozycyjnego.

Ponieważ liczbę zmiennoprzecinkową można zapisywać w różny sposób, przyjęto tzw. postać znormalizowaną.

 

Znormalizowana liczba zmiennoprzecinkowa to taka, w której mantysa spełnia nierówność:

p > | m | ≥ 1

 

Według tej definicji z podanych na początku rozdziału zapisów zmiennoprzecinkowych postacią znormalizowaną jest jedynie zapis 3,25 × 1022.

 

Przeliczanie liczb na zapis zmiennoprzecinkowy

Jeśli dokładnie przeczytaliście ze zrozumieniem poprzednie rozdziały naszego opracowania, to zadanie przeliczania liczb z systemu dziesiętnego na zapis zmiennoprzecinkowy w systemie o dowolnej podstawie jest dziecinnie łatwe. Jeśli nie, to proponuję to zrobić.

 

Algorytm przeliczania liczby dziesiętnej na liczbę zmiennoprzecinkową w innym systemie pozycyjnym
  1. Obliczamy mantysę przy cesze równej 0. W tym celu wystarczy przeliczyć daną liczbę dziesiętną, na liczbę w systemie docelowym.
  2. Normalizujemy mantysę modyfikując przy tym odpowiednio cechę liczby
  3. Koniec

 

Przykład:

Dla przykładu zapiszmy liczbę dziesiętną 1275,125 jako zmiennoprzecinkową liczbę w systemie czwórkowym.

Najpierw przeliczamy liczbę 1275,125 na system czwórkowy. Robimy to osobno dla części całkowitej i ułamkowej:

 

1275 div 4 =  318  i reszta 3
318 div 4 =  79  i reszta 2
79 div 4 =  19  i reszta 3
19 div 4 =  4  i reszta 3
4 div 4 =  1  i reszta 0
1 div 4 =  0  i reszta 1, koniec

 

1275(10) = 103323(4)

 

Teraz przeliczamy na system czwórkowy część ułamkową liczby:

 

0,125 × 4 =  0,5  - cyfra 0
0,5 × 4 =  2,0  - cyfra 2 i kończymy, ponieważ część ułamkowa wynosi 0

 

0,125(10) = 0,02(4).

 

Łączymy ze sobą oba wyniki i otrzymujemy postać czwórkową przeliczanej liczby dziesiętnej:

 

1275,125(10) = 103323,02(4)

 

Liczbę tę zapisujemy z cechą równą 0, czyli

 

103323,02 × 100(4)

 

Normalizujemy mantysę. W tym celu przecinek należy przesunąć o 5 pozycji w lewo, zatem cecha wzrośnie do wartości 5, co w systemie czwórkowym ma zapis 11(4) i ostatecznie:

 

1275,125(10) = 1,0332302 × 1011(4)

 

Zadanie to można rozwiązać również w inny sposób. Mantysę i cechę docelowej liczby zmiennoprzecinkowej możemy wyznaczyć w systemie dziesiętnym, a następnie liczby te przeliczyć na system docelowy. Korzystamy tutaj z faktu, iż przesunięcie przecinka w systemie docelowym odpowiada pomnożeniu wartości liczby przez podstawę tego systemu (przesunięcie w prawo) lub podzieleniu jej przez podstawę (przesunięcie w lewo). Zatem:

 

1275,125 = 1275,125 × 40
1275,125 = 318,78125 × 41
1275,125 = 79,6953125 × 42
1275,125 = 19,923828125 × 43
1275,125 = 4,98095703125 × 44
1275,125 = 1,2452392578125 × 45

 

Teraz otrzymane liczby wystarczy zamienić na system czwórkowy i mamy gotową zmiennoprzecinkową postać znormalizowaną przeliczanej liczby.

 

m = 1,2452392578125

 

Część całkowita wynosi 1, obliczamy zatem część ułamkową mantysy:

 

0,2452392578125 × 4 =  0,98095703125  - cyfra 0
0,98095703125 × 4 =  3,923828125  - cyfra 3
0,923828125 × 4 =  3,6953125  - cyfra 3
0,6953125 × 4 =  2,78125  - cyfra 2
0,78125 × 4 =  3,125  - cyfra 3
0,125 × 4 =  0,5  - cyfra 0
0,5 × 4 =  2,0  - cyfra 2 i koniec, gdyż część ułamkowa wynosi zero

 

m = 1,0332302(4)

p = 4(10) = 10(4)

c = 5(10) = 11(4)

 

Zatem ostatecznie:

 

1275,125(10) = 1,0332302 × 1011(4).

 

Zadania

Zadanie 1 (łatwe)

Oblicz wartość dziesiętną następujących liczb zmiennoprzecinkowych (pamiętaj, że wszystkie składniki liczby są zapisane w tym samym systemie pozycyjnym). Jeśli wynik jest ułamkowy, to wprowadź go w postaci części całkowitej i ułamka właściwego. Pomiędzy częścią całkowitą a ułamkiem musisz umieścić dokładnie jedną spację, np. 356 15/16.
F,3AC × 103(16) =   

.

72,61 × 101(8) =   

.

31,322 × 102(4) =   

.

122,021 × 102(3) =   

.

1011,11011 × 10100(2) =   

.

 

Zadanie 2 (łatwe)

Sprowadź podane liczby zmiennoprzecinkowe do postaci znormalizowanej (pamiętaj, że cecha musi być zapisana w podanym systemie pozycyjnym):
12 × 1049(10) = × 10^  

.

BFA,33 × 10AF(16) = × 10^  

.

7265,277 × 1073(8) = × 10^  

.

0,0032021 × 103(4) = × 10^  

.

1101,1111 × 1011(2) = × 10^  

.

 

Zadanie 3 (łatwe)

Przelicz podane liczby dziesiętne kolejno na zmiennoprzecinkowy system szesnastkowy, ósemkowy i dwójkowy. Wyniki przedstaw w postaci znormalizowanej.

 

1 × 105     5,12 × 102     27,25 × 10-2

I>
Zad. 1
Czy zawsze 0,2 + 0,1 = 0,3 ???



Wróć do spisu tematów
.