Ż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 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:
0,
,1
w reprezentacji binarnej. W przeciwnym wypadku należy dopisać 0
.Mam nadzieję, że przykład pozwoli Ci lepiej zrozumieć zasadę działania algorytmu. Zacznijmy od liczby 0,75.
0,
,1
. Postać binarna 0,1
. Wynik jest większy od 1 więc odejmuję jedynkę: 1,5 - 1 = 0,5,1
. Postać binarna 0,11
. Wynik jest równy 1 więc to koniec algorytmu,0,11
.Inny przykład, tym razem ułamek dziesiętny to 0,125:
0,
,0
. Postać binarna to 0,0
,0
. Postać binarna to 0,00
,1
. Postać binarna to 0,001
, koniec algorytmu,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:
0,
,0
. Postać binarna to 0,0
,0
. Postać binarna to 0,00
,0
. Postać binarna to 0,000
,1
i odejmuję 1 od wyniku. Postać binarna to 0,0001
,1
i odejmuję 1 od wyniku. Postać binarna to 0,00011
,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.
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
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
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.
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 |
---|
|
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).
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