5. BINARNY ZAPIS INFORMACJI

5.1. WIDOK Z LOTU PTAKA

Komputery to narzędzia do przetwarzania informacji. Użytkownik komputera może tworzyć, modyfikować, czy po prostu przeglądać (oglądać, słuchać itd.) informacje, zapisane w dokumentach tekstowych, plikach graficznych czy wideo, skoroszytach arkusza kalkulacyjnego czy zbiorach baz danych. Gry komputerowe i inne programy-symulacje to przykłady tzw. wirtualnej rzeczywistości, która istnieje tylko w postaci informacji zapisanej pamięci komputera i wyświetlonej (po jej interpretacji) na ekranie monitora. Komputery pozwalają na wykonywanie obliczeń liczbowych, jak i na przesyłanie informacji przez sieć komputerową. To wszystko byłoby niemożliwe, gdyby nie wymyślono jakiegoś sposobu na zapis (reprezentację) różnego rodzaju informacji w pamięci operacyjnej komputera, na dysku twardym i ich przesyłania przez sieć komputerową. 

Kluczową koncepcją, która pozwoliła uprościć problemy związane z projektowaniem i produkcją komputerów, ale również wpłynęła na niezawodność ich działania, jest koncepcja dwuwartościowego (binarnego) zapisu wszelkiego rodzaju informacji. Czasami mówi się o reprezentacji zerojedynkowej (0-1), choć w praktyce (w realizacji fizycznej) możemy mieć do czynienia z czymkolwiek, co może przyjmować dwa stany. Na przykład dla pamięci elektronicznej będzie to oznaczać wysoką lub niską wartość napięcia prądu elektrycznego, a dla tradycyjnego dysku twardego – namagnesowanie małych fragmentów warstw magnetycznych (północ – południe).

W tym podręczniku (jak i w innych miejscach) będziemy posługiwać się „0” dla ilustracji jednego ze stanów i „1” – dla drugiego z nich. Oznacza to np., że fragment pamięci elektronicznej komputera, dla którego wartości napięcia elektrycznego to: „niska”, „niska”, „wysoka”, „niska”, „wysoka”, „wysoka”, „wysoka”, „wysoka”, „niska”, „wysoka”, „niska”, „niska” będziemy przedstawiać jako ciąg cyfr 001011110100. Taka notacja jest powszechnie używana. Należy jednak pamiętać, że sformułowanie typu „komputer zapisuje informacje w postaci ciągu 0 i 1” jest skrótem myślowym. Nie ma sposobu, żeby zrobić to bezpośrednio – komputery posługują się mechanizmami fizycznymi takimi jak wysokie i niskie napięcie, namagnesowanie północ/południe, czy ciemne i jasne materiały.

Z żargonu informatycznego

Ponieważ używa się tylko dwóch cyfr: 0 i 1, więc mówi się też o systemie dwójkowym, zerojedynkowym lub binarnym (ang. binary system) i cyfrach dwójkowych (binarnych), zwanych bitami (ang. bit to skrót od słów „binary digit”). Pojęcie bitu jest jednym z najbardziej znanych pojęć w żargonie informatycznym. 

Każdy utworzony przez Ciebie plik, każde zdjęcie zapisane na dysku komputera, każdy dokument pobrany z Internetu to po prostu krótszy lub dłuższy ciąg bitów. Choć informatycy na co dzień nie zajmują się bezpośrednio analizowaniem tych ciągów bitów, to wiedza na temat zasad binarnego zapisu informacji jest naprawdę istotna, gdyż pozwala np. na oszacowanie przestrzeni na dysku, potrzebnej do zapisu danych z odpowiednią jakością. Podczas lektury tekstów z różnych dziedzin informatyki możesz napotkać określenia typu „24-bitowy kolor”, „128-bitowe szyfrowanie”, „32-bitowy adres IP” czy „8-bitowy kod ASCII”. Wiedza na temat zapisu binarnego jest niezbędna informatykowi do oszacowania ilości miejsca na dysku potrzebnego do zapisania wysokiej jakości informacji o kolorze, określenia bezpieczeństwa wybranej metody szyfrowania, do wyboru odpowiedniej długości klucza podczas projektowania bazy danych, czy zastosowania kodowania odpowiedniego dla teksów języka, w których występują znaki spoza alfabetu języka angielskiego.

Ten rozdział przedstawia różne metody, jakie są używane w systemach komputerowych do zapisania różnego rodzaju informacji za pomocą ciągów bitów oraz to, jak wybór metody wpływa na koszt i jakość tego, co robimy na komputerze i czy w ogóle da się to zrobić.

5.2. ZACZYNAMY

Ponad 200 lat temu 15-letni Francuz wymyślił system zapisu tekstu (liter, cyfr, znaków przestankowych itd.) z użyciem tzw. sześciopunktów jako kombinację sześciu wypukłych punktów ułożonych w dwóch kolumnach po trzy punkty w każdej. System stał się bardzo popularny wśród osób niewidomych, gdyż umożliwił względnie szybki i niezawodny sposób „czytania” tekstu. Alfabet Louisa Braille'a można uznać za jeden z pierwszych przykładów „binarnego” zapisu informacji – używa się w nim bowiem tylko dwóch znaków (wypukły punkt lub jego brak), a mimo to odpowiednie ich kombinacje pozwalają na wydawanie całych książek, zarówno fachowych, jak i literatury pięknej.

The braille alphabet

Sprawdźmy, ile różnych wzorców (znaków) w alfabecie Braille's można uzyskać, używając sześciopunktu. Dla uproszczenia na rysunkach posługujemy się układami (par, trójek itd.) niezamalowanych lub zamalowanych małych okręgów.

Gdyby system Braille'a używał kombinacji tylko dwóch (pary) punktów, to wzorców (znaków) byłyby cztery.

Combinations of two dots

Gdyby używał kombinacji trzech punktów, to byłoby ich osiem.

Combinations of three dots

Można było zauważyć, że w drugim przypadku liczba wzorców jest dwa razy większa. Okazuje się, że dodanie każdego kolejnego punktu skutkuje podwojeniem liczby wzorców (dlaczego?). To znaczy, że dla czterech punktów liczba wzorców będzie równa 16, dla pięciu – 32, a dla sześciu – 64.

W obrębie sześciopunktu można uzyskać 64 wzorce (znaki). To wystarcza na oznaczenie liter alfabetu i innych znaków, takich jak np. cyfry czy znaki interpunkcyjne.

Alfabet Braille'a jest dobrą ilustracją przyczyny popularności binarnego zapisu informacji. Można sobie wyobrazić system używający trzech rodzajów kropek: niewypukłych, półwypukłych i wypukłych. Z pewnością wprawny czytelnik potrafiłby je rozróżnić, a wtedy do uzyskania 64 znaków wystarczyłaby kombinacja czterech kropek. Kłopot w tym, że potrzebne byłyby bardziej dokładne (precyzyjne) urządzenia do tworzenia kropek, a ludzie musieliby więcej uwagi poświęcać rozróżnianiu kropek podczas „czytania”. Wystarczyłoby wtedy, że kartka zostałaby przygnieciona, nawet bardzo nieznacznie, a informacja stałby się nieczytelna.

Urządzenia cyfrowe prawie zawsze używają dwuwartościowej (binarnej) reprezentacji. Przyczyny są zwykle podobne: dyski komputerowe i pamięć elektroniczna jest po prostu tańsza i mniejszych rozmiarów, jeśli wystarczy rozróżnić między dwoma skrajnymi wartościami (jak np. wysokie i niskie napięcie), a nie trzeba mierzyć subtelnych różnic w wartościach (np. między wartościami napięcia). Operacje arytmetyczne w przypadku systemu binarnego wykonuje się w prosty sposób; nie ma zbyt wielu reguł – dodawanie wymaga tylko tego, by elektroniczne układy cyfrowe radziły sobie z obliczaniem: 0+0, 0+1, 1+0 i 1+1. Ile kombinacji sum jest w przypadku arytmetyki dziesiętnej?

Istotnie, każdego rodzaju informacja w komputerze jest zapisywana jako całe mnóstwo cyfr binarnych (dwójkowych) – tekst, obrazy, skoroszyty arkusza kalkulacyjnego, strony internetowe, pliki muzyczne z piosenkami – wszystko ma reprezentację dwuwartościową. Nawet programy komputerowe na Twoim komputerze mają postać binarną. Dlatego za mylące należy uznać wyróżnienie niektórych plików i określanie ich jako „pliki binarne”, gdyż każdy plik w komputerze ma postać binarną!

5.3. BINARNY ZAPIS TEKSTU

W poprzednim podrozdziale stwierdziliśmy, że sześć punktów systemu Braille'a pozwala uzyskać 64 różne wzorce (znaki). Spróbuj policzyć, ile różnych dużych liter, małych liter, liczb i innych znaków możesz wprowadzić do edytora tekstu, używając klawiatury komputerowej. (Nie zapomnij o znakach, które współdzielą klawisze z liczbami i o znakach interpunkcyjnych!) 

Czy użycie układów sześciu punktów (pozwalających na zapis 64 kombinacji) wystarczy, by zapisać wszystkie ww. znaki? Jeśli ktoś dokładnie policzył, to wie, że znaków jest więcej niż 64! Ilu punktów potrzeba, aby móc zapisać wszystkie znaki dostępne z klawiatury?

Okazuje się, że dla języka angielskiego wystarczy zastosować system 7-bitowy, który pozwala na uzyskanie 128 znaków. Takim systemem jest kod ASCII, stosowany w technice komputerowej i telekomunikacji już od roku 1963. Pomimo wielkich zmian w konstrukcji komputerów i systemów operacyjnych, kodowanie ASCII jest ciągle podstawą komputerowych systemów zapisu tekstu w języku angielskim.

Koncepcją zastosowaną w ASCII było przypisanie różnych wzorców bitowych każdemu ze znaków stosowanych w tekstach angielskich (oraz pewnej liczbie tzw. znaków sterujących, używanych dawniej w aparatach dalekopisowych – dziś tylko niektóre z nich mają zastosowanie w technice komputerowej, ale ten wątek pominiemy). W dzisiejszej postaci kodu ASCII dla języka angielskiego stosuje się wzorce 8-bitowe (oktety bitów, czy bajty), w których pierwszy bit ma zawsze wartość 0, co znaczy, że kod pozwala na zapis 128 znaków.

W tabeli przedstawiono zestawienie znaków i odpowiadajacych im wzorców 7-bitowych:

Postać binarna Znak Postać binarna Znak Postać binarna Znak
0100000 spacja (odstęp)
1000000 @ 1100000 `
0100001 ! 1000001 A 1100001 a
0100010 1000010 B 1100010 b
0100011 # 1000011 C 1100011 c
0100100 $ 1000100 D 1100100 d
0100101 % 1000101 E 1100101 e
0100110 & 1000110 F 1100110 f
0100111 1000111 G 1100111 g
0101000 ( 1001000 H 1101000 h
0101001 ) 1001001 I 1101001 i
0101010 * 1001010 J 1101010 j
0101011 + 1001011 K 1101011 k
0101100 , 1001100 L 1101100 l
0101101 - 1001101 M 1101101 m
0101110 . 1001110 N 1101110 n
0101111 / 1001111 O 1101111 o
0110000 0 1010000 P 1110000 p
0110001 1 1010001 Q 1110001 q
0110010 2 1010010 R 1110010 r
0110011 3 1010011 S 1110011 s
0110100 4 1010100 T 1110100 t
0110101 5 1010101 U 1110101 u
0110110 6 1010110 V 1110110 v
0110111 7 1010111 W 1110111 w
0111000 8 1011000 X 1111000 x
0111001 9 1011001 Y 1111001 y
0111010 : 1011010 Z 1111010 z
0111011 ; 1011011 [ 1111011 {
0111100 < 1011100 \ 1111100 |
0111101 = 1011101 ] 1111101 }
0111110 > 1011110 ^ 1111110 ~
0111111 ? 1011111 _ 1111111 <DEL>

Przykład: Litera c (mała litera) ma w tabeli przypisany wzorzec: „01100011” (0 na początku jest dopełnieniem kodu do 8 bitów). Litera o ma wzorzec „01101111”.
Warto w ramach ćwiczenia zapisać jakieś angielskie słowo, używając kodu ASCII i dać komuś innemu, kto również zapoznaje się z tym tematem, do odkodowania.

W komputerach teksty w języku angielskim są zapisywane w postaci ciągów (sekwencji) wzorców 8-bitowych, o których była mowa wyżej. Dla przykładu słowo „computers” będzie zapisane jako: 01100011 01101111 01101101 01110000 01110101 01110100 01100101 01110010 01110011.

Jak zapisać słowo „science”, używając kodu ASCII? A słowo „Wellington” (zauważ, że słowo rozpoczyna się dużą literą „W”)? Jak zapisać „358” (czyli ciąg trzech cyfr)? Zapisz całe zdanie: „Hello, how are you?” (odszukaj w tabeli kodów ASCII wzorca dla przecinka, znaku zapytania i spacji).

Ciekawostka

Gdyby pominąć konieczność rozróżniania dużych i małych liter, można by zastosować wzorce 5-bitowe. Spójrz do tabeli kodów ASCII i sprawdź, czy ostatnie pięć bitów kodów którejś z małych liter są identyczne. Porównaj też ostatnie pięć bitów kodów każdej z dużych liter.

Być może zauważysz, że wszystkie małe litery mają różne ostatnie pięć bitów w kodzie ASCII, ale każda mała i odpowiadająca jej duża litera mają przypisane identyczne ostatnie pięć bitów!

Przykłady:
a = 1100001 i A = 1000001, wzorzec 00001 jest identyczny dla ostatnich pięciu bitów.
s = 1110011 i S = 1010011, wzorzec 10011 jest identyczny dla ostatnich pięciu bitów.

Gdyby zamiast kodów 8-bitowych stosować 5-bitowe, to wówczas słowo „water” byłoby reprezentowane jako sekwencja postaci: 10111 00001 10111 10100 10010

There’s an activity that uses five-bit text codes hidden in music here.

Dla tekstów w języku angielskim kod ASCII jest wystarczającym rozwiązaniem. Co jednak zrobić w przypadku języków takich, jak chiński, w których stosuje się tysiące różnych znaków? 128 kombinacji zerojedynkowych to za mało! Wrócimy do tego ważnego tematu w dalszej części podręcznika. Najpierw musimy dowiedzieć się, jak w systemie binarnym zapisuje się liczby.

Ciekawostka

Nazwa „ASCII” jest skrótem od „American Standard Code for Information Interchange”. Była to standaryzacja sposobu kodowania znaków w maszynie dalekopisowej (zautomatyzowanym systemie telegraficznym). Dlatego system ASCII zawiera takie „znaki” dla sygnału dzwonka, dla informacji o potrzebie usunięcia poprzedniego znaku (jakby przodek polecenia „cofnij”), czy dla potwierdzenia zakończenia transmisji (END).
We fragmencie tabeli ASCII, zamieszczonym powyżej, znajdziesz tylko jeden z nich (DEL). Resztę pominięto.  
Dzisiaj system ASCII został wyparty przez kodowanie UTF-8. Należy podkreślić, że teksty angielskie zakodowane w UTF-8 mają identyczną reprezentację binarną, co teksty w ASCII, gdyż pierwszy bit każdego 8-bitowego wzorca jest wówczas równy 0. Inaczej mówiąc plik tekstowy zawierający wzorce 1xxxxxxx z całą pewnością nie jest zapisany w kodzie ASCII i zawiera informacje o znakach spoza alfabetu angielskiego.

Warto wspomnieć, że zanim pojawił się standard ASCII w usługach telegraficznych stosowano inne standardy: kod Baudota i EBCDIC.

5.4. BINARNY ZAPIS LICZB

Człowiek posługuje się zwykle pozycyjnym systemem liczbowym o podstawie 10 (zwanym też dziesiętnym). Warto przypomnieć sobie koncepcję zapisu pozycyjnego, gdyż system dwójkowy (binarny) jest również systemem pozycyjnym, choć używa się w nim mniejszej liczby cyfr!
Przykład: Liczba 123 = 100 + 20 + 3 = 1*100 + 2*10 + 3*1. Wartość (mnożnik) każdej z cyfr zależy od jej pozycji w zapisie. Mnożnik cyfry na danej pozycji jest 10 razy więszky niż mnożnik cyfry na pozycji po prawej. W konsekwencji możemy mówić o jednościach, dziesiątkach, setkach, tysiącach, dziesiątkach tysięcy, setkach tysięcy, milionach itd. Na każdej z pozycji może wystąpić jedna z dziesięciu cyfr (0,1,2,3,4,5,6,7,8,9).

Warto wspomnieć, że liczbę można zapisać w postaci rozwinięcia (szeregu potęgowego). Wówczas np. liczba 90 328 ma zapis:
90000 + 300 + 20 + 8 = (9 x 10000) + (0 x 1000) + (3 x 100) + (2 x 10) + (8 x 1) =
= (9 x 104) + (0 x 103) + (3 x 102) + (2 x 101) + (8 x 100)

5.4.1. Liczby dwójKowe (binarne)

Jak wspomniano wcześniej, komputery zapisują informacje używając bitów, czyli rozróżniając tylko dwa możliwe stany (dwustanowo). To oznacza, że w komputerze nie jest możliwe zapisanie liczby w systemie dziesiętnym, używając cyfr od 0 do 9, jak to czyni człowiek. Używany jest system o podstawie 2, zwany dwójkowym (binarnym).

W systemie binarnym (systemie o podstawie 2), można stosować wyłącznie dwie cyfry (0 i 1). W zapisie pozycyjnym mnożnik (wartość) każdej z cyfr jest więc dwa razy większy niż mnożnik cyfry po prawej stronie (inaczej niż w systemie dziesiętnym, gdzie tym czynnikiem jest 10).

Interaktywne narzędzie poniżej ma pomóc w zrozumieniu zasady zapisu binarnego. Warto wykonać kilka prób (ćwiczeń). Wartość dziesiętna liczby jest wyświetlana na końcu po prawej stronie.

Aby upewnić się, że właściwe posługujesz się narzędziem, sprawdź, czy po wpisaniu 101101 widzisz odpowiedź 45, po wpisaniu 100000 – 32, a po wpisaniu 001010 – 10 (dziesięć).

Spróbuj użyć tego narzędzia do zamiany liczby zapisanej dziesiętnie na postać binarną.
Przykład:
Wybierz liczbę mniejszą niż 61 (np. numer Twojego domu przy ulicy, wiek kolegi czy koleżanki, dzień miesiąca Twojego urodzenia).  Ustaw wszystkie cyfry binarne na 0, a następnie zacznij wybierać właściwe cyfry zaczynając od skrajnej lewej cyfry (32). Za każdym razem zdecyduj, czy wybrać 0 czy 1.
Czy stosujesz metodę prób i błędów? Na czym polega Twoja metoda zamiany (konwersji) liczb?

Czy potrafisz znaleźć zapis binarny liczby 23 bez posługiwania się narzędziem? A liczby 4, 0 i 32? Sprawdź teraz , czy dobrze myślisz, używając narzędzia.

Jaka jest największa liczba, jaką można uzyskać, posługując się tym narzędziem? Jaka jest najmniejsza? Czy jest jakaś liczba pomiędzy nimi, której nie jesteś w stanie uzyskać?

Prawdopodobnie jest już dla Ciebie jasne, że gdy lewy skrajny („najbardziej znaczący”) bit ustawiasz na 1, to wartość dziesiętną powiększasz o 32. Podobnie ustawiając bity położone dalej na prawo dodajesz odpowiednio 16, 8, 4, 2 i 1. Gdy bit ustawiasz na 0, wartość dziesiętna nie zwiększa się. Szukanie zapisu binarnego liczby jest więc związane z przedstawieniem liczby jako sumy niektórych lub wszystkich liczb ze zbioru: 32, 16, 8, 4, 2, 1, przy czym każda z liczb może wystąpić tylko raz.

Czy potrafisz sformułować jakieś systematyczne (metodyczne) podejście, różne od metody prób i błędów, pozwalające znaleźć zapis binarny liczby? Spójrz na liczbę, której zapis dwójkowy ma postać 100000. A teraz spójrz na  011111. Czy można uzyskać liczbę większą od 32, jeśli najbardziej znaczący bit jest ustawiony na 0? Dlaczego?
Spójrz na parę: 001000 i 000111. Dostrzegasz jakąś prawidłowość, która pozwoliłaby na sformułowanie jakiejś systematycznej metody zamiany (konwersji)? Wskazówka: Zacznij od lewego skrajnego bitu, a następnie analizuj sytuację bit po bicie, przesuwając się w prawo.

Co stałoby się, gdybyśmy mieli mniej niż sześć bitów? Przykład: Dla pięciu bitów, wartości na kolejnych pozycjach byłyby równe odpowiednio: 16, 8, 4, 2 i 1. Więc największą liczbą byłaby 11111, czyli 31 (dziesiętnie). Jaką największą liczbę zapiszemy, używając czterech bitów? Trzech bitów?

Co stałoby się, gdybyśmy mieli do dyspozycji nie sześć, a siedem bitów? Siódmy bit miałby wartość 64 i w konsekwencji moglibyśmy zapisać liczby aż do 127.

Dla zainteresowanych

Pomyśl, jak w sposób systematyczny liczyć w systemie binarnym, począwszy od 0. Tj. 0, 1, 2, 3 itd. aż do największej liczby możliwej do zapisania z użyciem sześciu bitów.
Zacznij od odliczenia od 0 do 16 i spróbuj dostrzec jakąś zasadę. Wskazówka: Wyobraź sobie, że dodajesz 1 do liczby zapisanej dziesiątkowo, np. 7 + 1, 38 + 1, 19 +1, 99 + 1, 230 899 999 + 1 itd. Czy możesz ten sam pomysł zastosować dla liczb dwójkowych?

Pomyśl o tym, jak zastosować wiedzę o systemie dwójkowym (binarnym) do liczenia na palcach powyżej liczby 10. Jaką największą liczbę można „zapisać” używając dziesięciu palców? Wyobraź sobie, że będziesz używać też palców u nóg. Jaka wówczas będzie odpowiedź?

Ważnym pojęciem związanym z liczbami binarnymi jest zakres wartości, którą można zapisać przy użyciu danej liczby bitów (cyfr). Pojedynczy bit wydaje się mało użyteczny, ale wystarczy do zapisania informacji np. o stanie pola wyboru tak/nie. Grupa ośmiu bitów jest już bardziej użyteczna – pozwala na zapis wartości od 0 do 255, a więc wystarczy do przechowania informacji o czyimś wieku, dniu miesiąca itd.

Z żargonu informatycznego

Grupa ośmiu bitów (oktet) jest tak użyteczna, że ma swoją nazwę: bajt (ang. byte). Pamięć elektroniczna i przestrzeń dyskowa jest zwykle podzielona na bajty. Większe liczby są zapisywane z użyciem większej liczby bajtów. Przykład: Dwa bajty (16 bitów) pozwalają na przechowywanie liczb z zakresu od 0 do 65 535. Cztery bajty (32 bity) umożliwiają na zapis liczb aż do 4 294 967 295. Możesz sprawdzić, czy te liczby są poprawne, badając mnożniki odpowiadające bitom. Każdy kolejny bit oznacza podwojenie zakresu liczb.

Ciekawostka

Świeczki na torcie urodzinowym to przykład zastosowania systemu jedynkowego (unarnego).  Kolejne liczby tworzy się przez powtarzanie  znaku 1 tyle razy, ile wynika to z wartości danej liczby (można więc powiedzieć, że mnożnik dla każdej pozycji jest równy 1). Przykład: 3 to 111, a 10 to 1111111111.
Wraz z wiekiem pojawi się problem – stulatek powinien uważać, aby nie wywołać pożaru, gdy będzie zdmuchiwać zapalone świeczki.

The image shows two people with birthday cakes, however a cake with 100 candles on it turns into a big fireball!

Na szczęście dla świeczek na torcie urodzinowym zamiast systemu jedynkowego, można użyć dwójkowego: świeczka świeci się lub nie. Przykład: Na przyjęcie z okazji osiemnastych urodzin wystarczy pięć świeczek (i tylko dwie będą się świecić!), gdyż zapis binarny tej liczby to 10010.

Tutaj możesz zobaczyć wideo, na którym ktoś liczby na palcach do 1023, a ktoś innym otrzymuje „binarny” tort urodzinowy.

It's a lot smarter to use binary notation on candles for birthdays as you get older, as you don't need as many candles.

5.5. Skrót dla liczb dwójkowych

Komputery zapisują liczby binarne i posługują się nimi, przetwarzając dane. Na ekranie zwykle wyświetlane są już w postaci dziesiętnej, gdyż wielocyfrowy zapis dwójkowy byłby dla człowieka kompletnie nieczytelny. Czasami jednak musimy posłużyć się liczbami, które nie są zapisane dziesiętnie, np. przekazując innej osobie adres fizyczny karty sieciowej (adres MAC) lub określając precyzyjnie kolor na stronie internetowej (w kodzie HTML).

Wyobraź sobie, że masz przepisać na kartce 16-bitową liczbę:  0101001110010001.
Można zastosować wówczas zapis skrócony: grupujemy cyfry po cztery (w tym przypadku:  0101 0011 1001 0001), i zastępujemy każdą czwórkę zapisem dziesiętnym, co daje 5391. Pojawia się jednak mały problem: co z grupą bitów postaci 1111 (czyli 15)? Przecież mamy tylko cyfry od 0 do 9.
 
Rozwiązanie jest proste: wprowadzimy specjalne symbole dla cyfr od 1010 (10) do 1111(15), tj. posłużymy się literami od A do F.

W tym momencie mamy już 16 cyfr. Taki system liczbowy nazywamy szesnastkowym (heksadecymalnym) lub w skrócie hex. Zamiana (konwersja) reprezentacji między systemem binarnym a szesnastkowym jest bardzo prosta. To wyjaśnia, dlaczego system szesnastkowy jest bardzo powszechnie stosowany wtedy, gdy chcemy zapisać poza komputerem dużą liczbę binarną.

Oto kompletna tablica liczb 4-bitowych i ich szesnastkowych odpowiedników:

Postać binanrna
Postać szesnastkowa
0000 0
0001 1
0010 2
0011 3
0100 4
0101 5
0110 6
0111 7
1000 8
1001 9
1010 A
1011 B
1100 C
1101 D
1110 E
1111 F
Przykład: Największą liczbą 8-bitową jest 11111111. Można ją zapisać jako FF. Można sprawdzić, że w systemie dziesiątkowym jest to 255.
Największą liczbą 16-bitową jest  1111111111111111, czyli FFFF. Tzn. 65 535.

Poniższe interaktywne narzędzie pozwala na dokonanie zamiany systemu liczbowego z szesnastkowego na dziesiętny. Pamiętaj, że to tylko dodatek. Istotą tego podrozdziału jest to, aby postrzegać zapis szesnastkowy jako skrót zapisu binarnego. 

To, jakiego zapisu (reprezentacji) liczby należy użyć, zależy od konkretnej sytuacji. Reprezentacja binarna jest reprezentacją maszynową, ale jest nieodpowiednia dla człowieka. Zapis szesnastkowy to dobry sposób na skrócenie zapisu binarnego. Zapis dziesiętny jest używany wtedy, gdy człowiek musi odczytać wartość jakiejś liczby. Wszystkie trzy notacje są używane w informatyce.

5.6. BINARNY ZAPIS OBRAZÓW

Pewnie przypominasz sobie lekcje plastyki, na których mieszaliście farby różnych kolorów, chcąc drogą prób i błędów uzyskać inną barwę. Ile było z tym zabawy! Po wymieszaniu kolorów czerwonego,  i niebieskiego można było uzyskać purpurowy. Po zmieszaniu żółtłego i niebieskiego — zielony. Czerwony w połączeniu z żółtym dawał pomarańczowy. Pewnie próbowaliście również uzyskać czarny przez zmieszanie niebieskiego, czerwonego i żółtego w równych ilościach. Zwykle efekt przypominał bardziej ciemny brąz. Mieszając farby trzech podstawowych kolorów w różnych ilościach, razem z farbą białą lub czarną, uzyskiwaliście wiele różnych, nowych kolorów.

Być może już wiesz, że w atramentowych drukarkach komputerowych też stosuje się tylko trzy podstawowe kolory. To zestaw lepszy od tego z zajęć plastycznych: turkusowy (niebieskozielony, ang. cyan), purpurowy (ang. magneta) oraz żółty (ang. yellow), określany skrótem CMY. Ten sposób mieszania barw nazywa się subtraktywnym, ponieważ można mówić o odejmowaniu (pochłanianiu niektórych długości fal przez powierzchnię). Na początku płótno, czy kartka, jest białe (czyli od powierzchni kartki odbijają się wszystkie składowe), a nałożenie farb działa jak filtr i od koloru białego odejmowane są różne składowe.

Oczywiśce ekran monitora komputerowego (czy wydruk) nie zawiera informacji tylko o jednym kolorze. Obraz składa się z milionów pikseli, a a kolor każdego z nich może inny niż kolory sąsiadujących z nim pikseli.

Z żargonu informatycznego

Słowo piksel (ang. pixel) to skrót powstały z angielskiego zwrotu picture element, czyli element obrazu. Na ekranie monitora komputerowego obraz (grafika), to siatka pikseli  o różnych kolorach. Piksel ma wielkość ułamka milimetra, a więc obraz składa się zwykle z milionów pikseli (stąd mówi się megapiksel na oznaczenie zbioru miliona pikseli)

This image shows the small red, green, and blue pixels that are used on screens to display colour.

Kolory wyświetlane na ekranach telewizorów też uzyskuje się przez zmieszanie kolorów podstawowych: czerwonego (ang. red), zielonego (ang. green) i niebieskiego (ang. blue). Mamy tu jednak do czynienia z modelem addytywnym RGB : ekran na początku jest czarny, a inne kolory uzyskuje się jakby przez dodawanie kolorów (odcieni) trzech składowych subpikseli, świecących z różną intensywnością odpowiednio: na czerwono, na zielono i na niebiesko.

Możesz sprawdzić, jak to działa, używając małej aplikacji, zamieszczonej poniżej.
•    Zmieniaj ustawienia każdego z suwaków.
•    Jak uzyskać kolor żółty?
•    Jaki będzie efekt, gdy wszystkie suwaki ustawisz na 0? Jaki, jeśli wszystkie będą mieć wartość 255?
•    Co zobaczysz, gdy suwaki ustawisz w połowie?
•    Co się stanie, gdy jeden z suwaków będzie ustawiony do prawej, a dwa inne w połowie?
•    Jak uzyskać kolory: purpurowy, pomarańczowy i różowy?
•    Co się stanie, gdy wszystkie suwaki będą ustawione na tę samą wartość?
•    Jak uzyskać kolor czarny? A biały?

Kluczową koncepcją zapisu informacji graficznej jest to, że kolor piksela opisuje się, używając trzech liczb (składowych). W powyższym przykładzie były to liczby od 0 do 255. Dla każdej składowej mamy wtedy 256 możliwości, co umożliwia zapis informacji o 256 x 256 x 256 = 16 777 216 różnych kolorach. To więcej, niż ludzkie oko jest w stanie rozróżnić.

Ciekawostka

Ludzkie oko zawiera miliony światłoczułych receptorów, zwanych czopkami. Istnieją trzy rodzaje czopków: wywołujące odpowiednio wrażenie czerwieni, wrażenie zieleni i wrażenie barwy niebieskiej. Dla przykładu: jeśli na światło reagują z podobną czułością czopki z pierwszeej i trzeciej z wyżej wymienionych grup, a czopki z drugiej grupy nie reagują, to mózg postrzega tę barwę jako purpurową (ang. magenta).

Oczywiście, zazwyczaj na ekranie wyświetlany jest więcej niż jeden kolor. Dzisiaj nawet ekrany komputerowe najmniejszych rozmiarów zawierają miliony pikseli i w komputerze musi być zapisana informacja o kolorze każdego z nich. Współcześnie rozmiary zdjęć mierzy się używając jednostki zwanej MP, czyli megapikselem (=milion pikseli). W systemie komputerowym informacja o kolorze każdego z pikseli zapisywana jest w postaci trzech liczb (o tym była mowa wyżej). Oznacza to, że do zapisania pełnej informacji o zdjęciu rozmiaru 2MP potrzeba sześciu milionów liczb! Mamy tu na myśli oczywiście taki sposób zapisu, w którym nie stosuje się kompresji. 

5.6.1. BINARNY ZAPIS OBRAZÓW WYSOKIEJ JAKOŚCI

W jaki sposób binarnie, czyli w systemie dwójkowym, zapisać informację o kolorze? Wykonując ćwiczenie dotyczące składowych koloru (z suwakami), można było zauważyć, że suwak dla każdej składowej (czerwona, zielona, niebieska) był ustawiany w jednej z 256 pozycji (od 0 do 255). Do zapisania informacji składowej potrzeba zatem 8 bitów (ponieważ 28 = 2 x 2 x 2 x 2 x 2 x 2 x 2 x 2 = 256).

Są trzy składowe, więc potrzebujemy 24 (3 x 8 = 24) bity do zapisania informacji o kolorze piksela.

Liczbę 224 (czyli liczbę wszystkich liczb, które można zapisać używając 24 bitów) można wyznaczyć wykonując mnożenie: 256 x 256 x 256. Otrzymujemy 16 777 216. To oznacza, że zapis 24-bitowy pozwala zachować informację o ponad 16 milionach różnych kolorów. To nam wystarczy, aby mówić o zapisie wysokiej jakości (wierności). Czasami mówi się o pełnym kolorze (ang. true color).

Jak to w praktyce wygląda? Wydaje się, że najrozsądniej jest użyć równej liczby bitów dla każdej składowej koloru. W ćwiczeniu powyżej składowe kolorów były wyświetlane jako liczby dziesiętne. Aby uzyskać binarny zapis informacji o składowych, należy zapisać te liczby w systemie dwójkowym i ustawić te 8-bitowe ciągi zer i 1jedynek obok siebie w odpowiedniej kolejności w jeden ciąg 24-bitowy (najpierw wzorzec bitowy dla składowej czerwonej, później dla zielonej, a na końcu dla niebieskiej).

The colour purple.

Przykład: Wyobraź sobie, że składowe koloru to: czerwona = 145, zielona = 50 i niebieska = 123 (jeśli nie wierzysz, że to odcień purpurowego, możesz sam sprawdzić). Każdą z tych trzech liczb należy napisać binarnie, używając 8 bitów. Możesz to zrobić samodzielnie (np. posługując się tzw. pianinem binarnym). Otrzymasz: czerwona = 10010001, zielona = 00110010 i niebieska = 01111011. Informacja o kolorze (odcień purpury) będzie mieć zatem następujący wzorzec bitowy: 100100010011001001111011.

Zauważ, że nie zapisujemy odstępów między 8. i 9. bitem, ani między 16. i 17. bitem, by podkreślić, że w komputerze oczywiście nie ma miejsca na inny znak niż reprezentacja fizyczna 0 i 1. Dla wygody odczytu możesz jednak zapisywać odstępy (spacje), kiedy zapisujesz taką informację w edytorze tekstu, czy na długopisem na kartce. Zwróć uwagę na to, że każda składowa opisana jest z użyciem ośmiu bitów, nawet jeśli te najbardziej znaczące ustawione są na 0. W celu lepszego zrozumienia tego zagadnienia warto zapisać kilka innych przykładów.

5.6.2. SZESNASTKOWE KODY KOLORÓW

Podczas tworzenia kodu HTML strony internetowej często trzeba określać kolor tekstu, tła itd. Można wtedy podać wprost angielską nazwę koloru, np. "red", "blue", "purple" lub "gold". W ten sposób nie da się jednak opisać różnych odcieni koloru czerwonego, niebieskiego i innych. Jedynym rozwiązaniem jest wskazanie odpowiedniego kodu koloru. W praktyce nie stosuje się w tym miejscu zapisu binarnego (24 bitów), ale kody szestnastkowe, które są znacznie bardziej czytelne dla człowieka, więc pisze się np. #00FF9E. Znak # (ang. hash) to informacja dla przeglądarki internetowej, która kolejne sześć znaków zinterpretuje jako 24-bitową informację o kolorze. Takie "trójki szesnastkowe" stosuje się nie tylko w kodzie HTML, ale również np. w przypadku określania atrybutu koloru dla stylów w plikach CSS i SVG.

W przykładzie używanym we wcześniejszej części tekstu pojawił się następujący wzorzec bitowy: 100100010011001001111011. Ten 24-bitowy ciąg można rozdzielić na grupy półbajtów: 1001 0001 0011 0010 0111 1011. Jeśli zastapimy każdy z nich cyfrą szesnastkową, to otrzymamy 91327B. Taki kod nazwiemy kodem szesnastkowym (heksadecymalnym) koloru!

Dla przykładu: tworząc stronę internetową możemy w pliku HTML określić kolor tła strony, pisząc  <body bgcolor="#00FF9E">

Osoba, która rozumie, na czym polega tworzenie kodów szesnastkowych, potrafi z łatowścią dostosować kod koloru tak, aby uzyskać oczekiwany odcień koloru. Wiadomo, że w przypadku 24-bitowej głębi koloru, pierwsze osiem bitów (w konsekwencji pierwsze dwie cyfry szesnastkowe) określa wartość składowej czerwonej, kolejne osiem — zielonej, a ostatnie osiem — niebieskiej. Aby zwiększyć udział odpowiedniej składowej, wystarczy zmienić odpowiednio jej kod szesnastkowy. Na przykład zmiana kodu #000000 (kolor czarny) na #002300) da w efekcie odcień koloru zielonego. Jakie kolory uzyskamy, używając kodów: #FF0000, #FF00FF, #FFFFFF?

5.6.3. BINARNY ZAPIS OBRAZÓW Z UŻYCIEM MNIEJSZEJ LICZBY BITÓW

Wyobraźmy sobie sytuację, w której do zapisu informacji o kolorze mamy używać mniej niż 24 bitów. Wykonując eksperyment z użyciem narzędzia poniżej można się przekonać jaki będzie efekt zmniejszenia głębi koloru. Określ kolor klikając na obrazku po lewej stronie, a następnie spróbuj uzyskać odpowiednie dla wybranego koloru ustawienie suwaków 24-bitowych (po kilku próbach wyświetlony zostanie komunikat-wskazówka; zamiast myszy możesz używać strzałek na klawiaturze, aby precyzyjnie ustawić suwaki). Przekonasz się, że określony wcześniej kolor można precyzyjnie opisać, używając reprezentacji 24-bitowej.

Następnie spróbuj to powtórzyć dla suwaków w wersji 8-bitowej. W tym przypadku na opis składowych czerwonej i zielonej przypadać będzie jedna z ośmiu możliwych wartości, a dla niebieskiej — jedna z czterech wartości!

W przypadku drugiego zestawu suwaków (w wersji 8-bitowej), na zapis informacji o składowej czerwowej przeznaczone były trzy bity. Na zapis składowej zielonej również trzy bity, a dla składowej niebieskiej tylko dwa. Oznacza to, że wzorzec bitowy koloru może być jednym z 256 możliwych.

Inaczej mówiąc: trzykrotne zmniejszenie liczby bitów z 24 do 8 ma taki skutek, że nie jesteśmy w stanie odziwerciedlić wielkiej liczby odcieni koloru, a więc i przedstawić łagodnego przejścia (gradientu) między ocieniami koloru na obrazie. To jest dobra ilustracja problemu, przed jakim stoi projektant oprogramowania: użyć mniej pamięci (mniejszej liczby bitów), czy uzyskać lepszą jakość zapisu (reprezentacji) informacji?

Z żargonu informatycznego

Z informacją o liczbie bitów zastosowanych do zapisu informacji o kolorach pikseli wiąże się ściśle określenie „głębia koloru” (lub „głębia bitowa”). Przykład: obraz o 8-bitowej głębi koloru to taki, w którym każdy z pikseli ma przyspisany jeden z 256 kolorów palety barw. Trzeba podkreślić, że drastyczne zmniejszenie głębi koloru może dać taki efekt, że obraz będzie wyglądał bardzo dziwnie (utrata kolorów prowadzi do powstania fałszywych konturów). Czasami taki efekt jest sotosowany w programach graficznych specjalnie. Mówi się wtedy o efekcie posteryzcji (tj. upodobnieniu obrazu do plakatów, które drukuje się z użyciem tylko kilku kolorów).

Kolejne narzędzie (poniżej) pozwala zobaczyć, jaki będzie efekt stosowania coraz mniejszej palety (głębi) kolorów, łącznie z sytuacją pominięcia informacji o kolorze (0 bitów!). Możesz wybrać obraz z menu. W którym przypadku zmiana jakości jest najbadziej dostrzegalna? W którym mniej? Kiedy należy troszczyć się o w miarę pełne zachowanie informacji o kolorach? Kiedy nie ma to większego znaczenia (tj. wystarczy nam obraz dwukolorowy)?

Można zapytać, czy zyskalibyśmy coś zapisując informację o kolorze z użyciem liczby bitów większej niż 24? Okazuje się, że ludzkie oko potrafi rozróżniać ok. 10 milionów kolorów, więc liczba kolorów dla głębi 24-bitowej (ponad 16 milionów) jest większa. Czasami jednak stosuje się więcej bitów, np. w przypadku, gdy chcemy na obrazie odzwierciedlić kontrast.

Rodzi się pytanie: Czy warto zaoszczędzić na pamięci, tracąc na jakości obrazu? W przypadku obrazu zapisanego z użyciem 24 bitów na piksel o rozmiarach 800 x 600 pikseli liczba bitów informacji o obrazie będzie równa  600 x 800 x 24 bity = 11 520 000 bitów, czyli ok. 1,44 megabajta. Jeśli zastosujemy 8 bitów na piksel, zaoszczędzimy 2/3 tej pamięci, czyli prawie 1MB.

Współcześnie rzadko używa się już systemu 8-bitowego. Choć zdarza się, że stosuje się takie rozwiązanie np. w sytuacji zdalnej pracy na innym komputerze, z użyciem graficznego interfejsu użytkownika, kiedy nie ma szeropasmowego dostępu do sieci. Obraz pulpitu wygląda wtedy dziwnie, ale to nie ma wtedy większego znaczenia, bo ciągle jesteśmy w stanie wykonać pracę, którą zamierzaliśmy łącząc się z tym komputerem. Podobnie w przypadku tworzenia niektórych typów grafik, takich jak diagramy, czy rysunki czarno-białe (line art), stosuje się zmniejszoną liczbę bitów przy zapisie. Warto wspomnieć, że wiele ikon (pulpitu) jest 8-bitowych.

W sytuacji, kiedy chcemy uzyskać mniejszy rozmiar pliku z informacją graficzną, stosuje stosuje się powszechnie kompresję (np. dla formatów plików JPEG, GIF i PNG). Takie zapis wymaga jednak pewnego czasu przetwarzania obrazu przy zapisie oraz odczycie, a więc wydłuża się czas potrzebny np. na wyświetlenie obrazu.

Kolejne narzędzie (poniżej) pozwala na pracę z dowolnym obrazem (np. z Twojego komputera) i eksperymentowanie z przydzielaniem różnej liczby bitów do zapisu informacji o kolorze. Warto sprawdzić efekty na kilku przykładach, aby lepiej zrozumieć temat. Wybrany obraz z Twojego dysku przeciągnij myszką w miejsce obrazu w tej chwili wyświetlanego.

5.7. Więcej o binarnym zapisie tekstu

We wprowadzeniu to tematu o binarnym zapisie tekstu analizowaliśmy 8-bitowy kod ASCII (który w istocie jest kodem 7-bitowym i pozwala uzyskać 128 różnych znaków). Warto rozważyć, co zyskalibyśmy stosując inne reprezentacje (o większej lub mniejszej liczbie bitów).

W ciekawostce w podrozdziale wprowadzającym, pojawił się przykład kodu 5-bitowego, który jest wystarczający dla uproszczonego zapisu tekstu w języku angielskim. Można wyobrazić sobie sytuację, że system ten znalazłby zastosowanie w przypadku systemów kodowania o bardzo powolnej transmisji informacji, gdyż pozwoliłby na zaoszczędzenie czasu.
Warto przypomnieć, że system Braille'a jest przykładem kodu 6-bitowego i pozwala na uzyskanie 64 znaków. Zastosowanie kodu 8-bitowego w tym przypadku oznaczałoby potrzebę zużycia większej ilości papieru, ale i czas „czytania” wydłużyłby się.

W przypadku niektórych języków ich alfabet składa się z liczby znaków większej niż 32, 64, czy nawet 128. Tak naprawdę większość ludzkości posługuje się takimi językami! Niezbędne są więc dłuższe kody. Najbardziej powszechnym jest system zwany Unicode. Jedna z jego wersji używa 16 bitów na znak. Oznacza to, że liczba znaków, jakie można uzyskać w tym kodzie to nawet 216 = 65 536.
Istnieją też standardy kodowania, które pozwalają na użycie nawet 32 bitów (czterech bajtów) dla zapisu informacji o znaku.

Tablica znaków Unicode jest zbyt, zbyt obszerna, aby ją umieścić tutaj. Możesz różne jej wersje odszukać w Internecie i poszukać kodów dla różnych ciekawych znaków. Strona internetowa dostępna pod adresem http://unicode-table.com/en/ pokazuje znaki z informacją gdzie na świecie są one używane. 16- lub 32-bitowe kody znaków Unicode zwykle zapisuje się, używając notacji szesnastkowej.

Nowoczesne kody typu Unicode są kodami elastycznymi w sensie rozmiaru komputerowej reprezentacji różnych znaków w tym samym pliku tekstowym. To znaczy, że znaki, które pochodzą z kodu ASCII zapisuje się w reprezentacji 8-bitowej, a znaki z innych alfabetów w reprezentacji 16- lub 32-bitowej (w zależności od potrzeb). Do takich systemów kodowania należą np. Universal Character Set (UCS), the Unicode/UCS Transformation Format (UTF-8 UTF-16, etc.) oraz standard GB 18030 (używany na Tajwanie od roku 2000).

5.8. Zapis liczb w komputerze

Liczbami posługujemy się zwykle pracując z arkuszem kalkulacyjnym lub bazą danych. Trzeba zaznaczyć, że nie wszystkie informacje liczbowe, są zapisywane w komputerze jako liczby, a jako ciągi znaków, np. numer telefonu zapisany jako (03) 555-1234, a więc zawierający nawiasy i łącznik. Z drugiej strony informacje, które na pierwszy rzut oka nie są liczbami (np. „30 stycznia 2014”), mogą być ku naszemu zaskoczeniu zapisywane przez oprogramowanie jako liczby (co pozwala np. w programie Excel na odejmowanie jednej daty od drugiej, w celu wyznaczenia liczby dni pomiędzy dwoma wydarzeniami).

Każdy system komputerowy lub oprogramowanie, w którym zapisywane czy przetwarzane są liczby, przydziela w pamięci czy w pliku pewną liczbę bitów na zapis każdej liczby. Przykład: Sprawdź, z jaką maksymalną dokładnością (liczbą cyfr dziesiętnych) możesz zapisać np. liczbę 1/3 w arkuszu kalkulacyjnym. W niektórych systemach (np. w językach programowania Java czy C, lub systemie zarządzania bazą danych) możesz w pewnych granicach określić precyzję, z jaką zapisywane będą liczby, a w innych ta precyzja jest ustalona na stałe (np. w arkuszu kalkulacyjnym). Istnieją też systemy, w których precyzję zapisu możesz określić dowolnie (np. zakres liczb całkowitych w języku programowania Python).

Dość powszechnie stosuje się dwie metody komputerowej reprezentacji liczb: dla liczb całkowitych i liczb rzeczywistych. Ta druga reprezentacja określana jest jako liczby zmiennoprzecinkowe. Pozwala ona na zapis liczby niecałkowitej. W tym miejscu skupimy się na przedstawieniu metod zapisu liczb całkowitych. Temat reprezentacji zmiennoprzecinkowej jest trochę trudniejszy do zrozumienia (ale warto go poznać bliżej, jeśli się chce nimi posługiwać)!

Sposób zapisu liczb przedstawiony w jednym z wcześniejszych rozdziałów pozwalał na zapis tylko liczb nieujemnych. W praktyce często potrzebujemy również zapisywać informacje o wartościach ujemnych (np. o obciążeniu rachunku bankowego, czy temperaturze powietrza zimą!). Kiedy posługujemy się zapisem dziesiętnym, to liczbę ujemną uzyskujemy poprzez dopisanie znaku minus przed liczbą. W komputerze nie ma takiej możliwości, ale możemy przydzielić jeden dodatkowy bit, zwany bitem znaku. To może być skrajny lewy bit bajtu – gdy ustawimy go na „0”, to uznamy liczbę za dodatnią, a w przypadku „1” liczba będzie ujemna (analogia do znaku minus). 

Przykład: W reprezentacji 7-bitowej liczba 41 będzie zapisana jako 0101001, gdzie pierwszy bit (0) to bit znaku, a kolejne bity to zapis binarny liczby 41. Podobnie liczba -59 będzie mieć reprezentację 1111011, gdzie pierwszy bit (1) jest bitem znaku, a kolejne bity to liczba 59 zapisana binarnie.

Znajdź 7-bitową reprezentację binanrną liczb:  1, -1, -8, 34, -37, -88 i 102.
Jakie liczby będą reprezentowane jako 10000110, 01111111i  10000000 w przypadku systemu 8-bitowego?

Przykład  10000000 jest dobrą ilustracją jednej z wad, jaką ma wyżej opisany sposób notacji. Liczba 0 ma dwie reprezentacje: -0 i +0. To nie tylko kwestia rozrzutności, ale i źródło potencjalnego zamieszania.

Istnieje inny sposób zapisu zwany metodą „uzupełnienia do dwóch”, która nie tylko pozbawiona jest wyżej opisanej wady, ale znacznie ułatwia operacje arytmetyczne na liczbach ujemnych. Ten temat nie jest nam jednak niezbędny w tej chwili. Zainteresowani znajdą więcej na ten temat w ramce poniżej.

Dla zainteresowanych

Liczby ujemne najczęściej zapisuje się w systemach komputerowych, używając kodu (systemu) „uzupełnień do dwóch”. Jedną z jego zalet jest ujednolicenie arytmetyki (działania wykonywane z liczbą ujemną nie muszą być traktowane jako odrębny przypadek), co daje zysk szybkości oraz upraszcza projekt cyfrowych obwodów elektronicznych. 

System opiera się na prostym pomyśle dotyczącym zapisu liczb przeciwnych. Przykład: Chcesz od pewnej liczby wielocyfrowej odjąć 4. Dodaj najpierw 6, a następnie odejmij 10. Liczba 6 jest w tym przypadku „dopełnieniem”  liczby -4. Podobnie to działa w systemie dwójkowym. Jest nawet prostsze, bo operacje wykonuje się na dwóch cyfrach.

Ciekawostka

W niektórych językach programowania nie ma automatycznej kontroli, która pozwoliłaby stwierdzić, że nastąpiła próba zapisu zbyt dużej liczby (przepełnienie). Przykład: Dodanie 1 do liczby 127 w przypadku zapisu 8-bitowego zakończy się uzyskaniem liczby -128.
Innym przykładem jest tzw. problem roku 2038. Okazuje się, że 19 stycznia 2038 roku nastąpi błąd przepełnienia i błędnie będzie interpretowana data w oprogramowaniu, które do zapisu daty używa pewnego tradycyjnego jej zapisu jako liczby 32-bitowej. Z dość podobnym problemem mieliśmy do czynienia w roku 2000.

xkcd comment on NP complete

Sposób budowy elementów pamięci elektronicznej wymusza posługiwanie się w praktyce wielokrotnościami 8 bitów, czy 32 bitów (a nawet 64 bitów). To oznacza, że np. dla 32-bitowego zapisu liczby całkowitej pierwszy bit jest bitem znaku, a pozostałe 31 służą do zapisu wartości liczby.

Ile różnych liczb można zapisać w komputerze, który dla zapisu liczb używa 32 bitów? Jaką największą liczbę można zapisać? Pamiętaj, że każdy dodatkowy bit oznacza podwojenie zakresu liczb. Jeśli liczbę 64 podwoisz jeszcze 25 razy (a więc w końcu będzie 31-bitowa), to uzyskasz kolejno 128, 256, 512, 1024, 2048.... aż w końcu 2 147 483 648. Inaczej mówiąc: Używając 31 bitów możesz zapisać 2 147 483 648 różnych liczb, a największą możliwą będzie  2 147 483 647. To ponad 2 miliardy. Jeśli dodać bit znaku, to uzyskamy tzw. 32-bitową liczbę całkowitą ze znakiem do zapisu liczb od -2 147 483 647 aż do 2 147 483 647.

Jeśli liczba ma być zapisywana bez znaku, to używając 32 bitów można zapisać dwa razy więcej liczb nieujemnych, a największa to 4 294 967 295.

Ilu ludzi jest na świecie? Czy reprezentacja 32-bitowa jest wystarczająca do tego, aby każdej osobie przyporządkować numer? Ile bitów powinno być, żeby się przygotować na możliwy wzrost populacji?

Typ liczby
Zakres dla liczby bez znaku
Zakres dla liczby ze znakiem
8 bitów
od 0 do 255 od -128 do 127
16 bitów
od 0 do 65 535 od -32 768 do 32 767
32 bity od 0 do 4 294 967 295 od −2 147 483 648 do 2 147 483 647
64 bity od 0 do 18 446 744 073 709 551 615 od −9 223 372 036 854 775 808 do 9 223 372 036 854 775 807

Gdy chcesz zapisać wartość liczbową na komputerze i masz ograniczoną przestrzeń, trzeba uważnie wybrać odpowiedni sposób reprezentacji. Tak, aby wystarczyło na zapis liczby, a jednocześnie by nie marnować miejsca w pamięci. Należy wówczas rozważyć też to, czy przypadkiem liczba nie może przyjmować wartości ujemnych.

Przygotuj kilka różnych przykładów informacji liczbowych (zarówno takich, które wymagają uwzględnienia wartości ujemnych, jak i nie), które można zapisać używając reprezentacji 8-, 16-, 32- i 64-bitowych. Przykłady: Do zapisu informacji o wieku wystarczy liczba 8-bitowa bez znaku, ale liczba uczniów w Twojej szkole może wymagać już możliwości zapisania liczby 16-bitowej. Jakie znasz inne przykłady?

Podaj przykłady liczb, których nie da się zapisać używając żadnej z powyższych reprezentacji liczb całkowitych.

Dla zainteresowanych

Komputery pozwalają na reprezentację liczb w jeszcze innej postaci – jako liczby zmiennoprzecinkowe. Jak można je krótko scharakteryzować? Pamiętasz, że kolejne bity liczby zapisanej z użyciem czterech bitów, rozpatrując je od lewej, są powiązane odpowiednio z wartościami 8, 4, 2 i 1. Jaką kolejną wartość miałby następny element tego ciągu? A jeszcze kolejny?

Poniżej znajduje się interaktywne narzędzie, które pozwala na wyznaczenie niecałkowitych liczb dziesiętnych na podstawie ich reprezentacji binarnych. Znajdź reprezentację liczb 3,5. Następnie 2,8125. Czy dla 2,8 też się uda?

Ten system jest systemem stałoprzecinkowym, tzn. ustalona jest stała liczba cyfr na część całkowitą liczby i na część ułamkową. W przypadku liczb zmiennoprzecinkowych miejsce przecinka może się zmieniać (liczbę cyfr przeznaczonych na część ułamkową określa wartość wykładnika).

5.8.1. Liczby w językach programowania

Wiedza na temat ograniczeń komputerowej reprezentacji liczb jest istotna dla osoby zajmującej się programowaniem (np. w języku Python, Java, C, C++, C#), ponieważ programista musi dokonać wyboru typu danych. Jeśli źle wybierze, może nastąpić przepełnienie. Przykład: Jeśli programista zadeklaruje zmienną 16-bitową bez znaku, a następnie będzie w niej przechowywać informację o liczbie znaków w pliku tekstowym, to pojawi się błąd już w przypadku pliku o wielkości 65 kilobajtów.

Jeśli wielkość pamięci urządzenia komputerowego jest bardzo ograniczona (np. w małym przenośnym urządzeniu), programista nie będzie chciał rezerwować 32 bitów dla przechowywania informacji o liczbie, która nigdy nie przekroczy 100.
Zresztą, nawet jeśli w urządzeniu rozmiar pamięci jest bardzo duży, to świadomy programista, wiedząc że program będzie przechowywał w pamięci miliony danych liczbowych, do zapisu których wystarczą reprezentacje 8-bitowe, nie będzie marnował milionów bajtów pamięci i używał reprezentacji 16-bitowych.

Nie zawsze jest to takie oczywiste, jakie długości  mają reprezentacje różnych typów danych w językach programowania (nie wynika to z nazwy typu). Zwykle deklaruje się je używając nazw typu „int” lub „long”, z których wprost nie wynika rozmiar rezerwowanej pamięci. Przykład: W języku Java są następujące typy całkowitoliczbowe: 8-bitowy typ „byte”, 16-bitowy typ „short”, 32-bitowy „int” i 64-bitowy „long”. W niektórych przypadkach (jak np. typ „int” w języku C) rozmiar rezerwowanej pamięci zależy od wersji języka i typu (architektury) komputera. W innych przypadkach (jak np. w języku Python) reprezentacja liczby jest automatycznie dostosowywana, jeśli liczba jest zbyt duża!

5.9. Podsumowanie

Informacje na temat binarnego zapisu grafiki zawarte w tym rozdziale to informacje podstawowe. Celem rozdziału było ukazać zasadę cyfrowego (binarnego) zapisu informacji oraz zwrócić uwagę na problem kompromisu między rozmiarem danych a jakością.

W podrozdziale dotyczącym kolorów poprzestano na opisie binarnego zapisu nieskompresowanych obrazów w postaci „surowej” czy bitmapy (format BMP). W praktyce dla obrazów dużych rozmiarów używa się metod kompresji takich, jak JPEG, GIF lub PNG. Należy podkreślić, że w momencie utworzenia obrazu (zdjęcia), czy wyświetlania na ekranie w sposób nieunikniony obraz ma reprezentację „surową”, o jakiej była mowa w tym rozdziale, a wybór reprezentacji zawartej w niej danych będzie miał wpływ na jej jakość i na koszt urządzenia wyświetlającego. 

Binarna reprezentacja liczb jest obszernym tematem, któremu poświęca się odrębne badania naukowe. Wybór komputerowej reprezentacji ma ogromny wpływ np. na szybkość operacji arytmetycznych, dokładność wyniku oraz zapotrzebowanie na pamięć czy miejsce na dysku. Dla reprezentacji zmiennoprzecinkowych określono standardy (najbardziej znany to  IEEE 754), aby ułatwić projektowanie sprzętu komputerowego, który będzie zajmować się przetwarzaniem takich liczb.
Arkusz kalkulacyjne zwykle używają reprezentacji zmiennoprzecinkowej do zapisywania wartości liczbowych, co wpływa na dokładność wykonywanych obliczeń (zwykle 64 bity na  każdą liczbę). Możesz sprawdzić, jakie są ograniczenia skończonej komputerowej reprezentacji liczb rzeczywistych np. wykonując w arkuszu kalkulacyjnym dodawanie bardzo dużej liczby i bardzo małej liczby.

Ten rozdział nie zwierał informacji na temat zapisu binarnego innego typu danych takich, jak np. pliki dźwiękowe i pliki wideo.

Computer Science Field Guide is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

Produced by Tim Bell, Jack Morgan, and many others based at the University of Canterbury, New Zealand.

Tłumaczenie: Paweł Perekietka, dr Michał Ren.