1 Reprezentacja danych Różne sposoby przechowywana

Transkrypt

1 Reprezentacja danych Różne sposoby przechowywana
Reprezentacja danych
Różne sposoby przechowywana danych w komputerze
- Wszelka informacja przetwarzana przez system komputerowy jest ciągiem zer i
jedynek. Niczym więcej.
- Z punktu widzenia systemu KAŻDA informacja to strumień zer i jedynek.
- Ten sam ciąg zer i jedynek raz może być zdjęciem naszego przyjaciela innym
razem Koncertem Bacha, a jeszcze innym razem listem do cioci. TEN SAN CIĄG! To
od nas zależy jak komputer będzie dany ciąg zer i jedynek rozumiał.
- To my, czyli użytkownik, mówimy jak interpretować dany ciąg zer i jedynek.
- Od sposobu interpretacji zależy co tak naprawdę odczytamy.
- To nie plik graficzny informuje nas o tym, że jest plikiem graficznym, ale to my
plik interpretujemy jak gdyby był plikiem graficznym (Oczywiście większość
współczesnych plików zawiera w sobie informacje o przenoszonych danych, ale
jest to tylko i wyłącznie po to aby ułatwić Życie.)
Kilka analogii
Analogia językowa
Co oznacza słowo: para
jeśli wiemy, że jest to słowo języka polskiego, to: coś;
jeśli wiemy, że jest to słowo języka angielskiego, to: coś innego.
Mimo że tak samo się pisze i tak samo wymawia, ale w zależności od języka znaczy co
innego.
Analogia liczbowa
Liczba osiem może być zapisana jako
8 w dziesiętnym systemie liczbowym;
VIII w rzymskim systemie liczbowym;
1000 w dwójkowym systemie liczbowym.
O kodowaniu czego mówić będziemy
znaki alfanumeryczne
liczby naturalne
liczby całkowite
liczby rzeczywiste
plik graficzny bmp
pakiet TCP/IP
1
Znaki alfanumeryczne
Znakiem alfanumerycznym nazywamy litery, cyfry a także pewne symbole jak np. (, :, +
itp. czyli wszystko to co możemy wpisać z klawiatury.
Kodowanie
Kodowaniem nazwiemy proces zamiany znaku wpisanego z klawiatury lub innego urządzenia
wczytującego na jego reprezentacje cyfrowa, czyli zapisanie jego przy pomocy ciągu zer i
jedynek.
ASCII American Standard Code for Information Interchange. W kodowaniu tym określono
kody dla:
małych (97-122) i dużych (65-90) liter alfabetu łacińskiego;
cyfr (48-57);
pewnej grupy znaków jak np. (, :, + itp. (32-47, 58-64, 91-96, 123-126);
niedrukowalnych znaków sterujących przepływem danych, np. ACK – potwierdzenie,
czy BEL – sygnał dźwiękowy (0-31).
Kodowanie w tym standardzie było najwcześniejsze. Dzięki niemu możemy zakodować każdy
znak alfanumeryczny. Koduje na liczbach 0-126, jest jeszcze liczba 127 ale ona jest inną
bajką. By zapisać 126 liczb potrzebujemy 7 bitów. A większość komputerów zwłaszcza z
dawnych czasów wykorzystywała 8 bitów lub wielokrotność 8, dlatego mimo że potrzeba
było 7 bitów to i tak rezerwowano tych bitów osiem, czyli 0-255, zatem pierwsze 128 miejsc
było wykorzystywanych, a pozostałe 128 już nie.
Znaki alfanumeryczne
Zakres kodów ASCII rozciąga się od 0 do 127, czyli wymaga wykorzystania co
najmniej 7 bitów. Ponieważ większość komputerów była 8-bitowa (czyli posługująca się
informacjami dzielonymi na kawałki po 8 bitów), wiec pozostawało jeszcze 128 wolnych
miejsc o numerach od 128 do 255. Znaki ASCII nie pokrywały zapotrzebowania narodowości
posługujących się literami alfabetu łacińskiego ze specyficznymi znakami diakrytycznymi
(Niemcy, Polska) lub wręcz zupełnie niestandardowymi znakami (Grecja, Rosja). Ze względu
na powstałe zapotrzebowanie, do reprezentacji znaków narodowych wykorzystano wolne 128
pozycji.
Szkoda tylko, ze każda narodowość zrobiła to niezależnie od innych. W ten oto
sposób powstały strony kodowe, czyli zestawy 255 znaków o wspólnej pierwszej połowie,
natomiast różniące się zasadniczo w drugiej. Dlatego manipulując jakimkolwiek tekstem,
jeśli chcemy poprawnie odczytać niestandardowe znaki alfabetu łacińskiego, MUSIMY
wiedzieć przy pomocy jakiej strony kodowej został on zapisany. Czyli posługując się jedną
stroną kodową nie mogliśmy napisać czegoś w wielu językach, bo na jednej stronie są znaki
tylko jednego języka. Poza tym dla niektórych języków typu polski było tak, że powstało
kilka stron kodowych, bo autorzy nie chcieli się dogadać…
Strony kodowe znaków polskich
2
ISO 8859-2, nazywane także latin2, jest kodowaniem charakterystycznym dla systemów
rodziny UNIX-owych. Obecne na prawie całym świecie.
CP 1250, nazywane także win-1250, jest kodowaniem charakterystycznym dla systemów
rodziny Windows. Część kodu się pokrywa z powyższym, ale tylko część, dlatego dokumenty
przeniesione z Unixa na windowsa ma część polskich znaków, ale tylko część.
Mazowia –kodowanie opracowane na potrzeby polskiego komputera Mazovia.
Unicode – o tym dalej. Ostatnio właśnie on obowiązuje i jest po to, by zaradzić istniejącym
problemom niejednoznaczności kodowania, bo każdy kodował wg innej strony kodowej czy
jak pracujemy nad dokumentem wielojęzycznym. Obecnie w Unicode istnieją wszystkie znaki
jakie zna ludzkość. WWW.unicode.org
Problemy
Oczywisty – wiele różnych stron kodowych nawet dla tego samego języka.
Trudności z obsługa tekstów wielojęzycznych.
Zbyt mała przestrzeń dla kodów niektórych języków, np. chiński.
Unicode – najważniejsze cechy
Jednoznaczność.
Jeden kod odpowiada jednemu znakowi i odwrotnie. ZAWSZE.
Uniwersalność.
Wszystkie powszechnie używane języki oraz symbole są tu dostępne, jest nawet pismo
ludów pierwotnych. Czyli bez względu Nd jakim dokumentem pracujemy możemy wyrazić
wszystkie znaki jakie są nam potrzebne.
Efektywność.
Identyfikacja znaku nie zależy od sekwencji sterującej czy znaków następujących bądź
poprzedzających. Bo np. chińczycy nie chcieli czekać aż będą stworzone znaki dla nich i
wymyślili sekwencje sterujące, czyli znaki, które potem zmieniają znaczenie następnych
znaków np. często znakiem sterującym był esc i my też tak będziemy pisać
%BG oznacza %BG to po prostu napis
escBG oznacza np., jakiś znaczek w języku chińskim
Manipulowanie tekstem zapisanym w ten sposób z sekwencją sterującą było bardzo
uciążliwe, trzeba było uwzględniać nie tylko sam znak, ale też jego otoczenie.
Identyfikacja nie reprezentacja.
Istotny jest dla nas sam znak a nie jego wygląd.
Znaczenie.
Własności znaków (np. kolejność alfabetyczna) nie zależą od położenia w tabeli kodów, ale
są określone w tablicy własności. Łatwo jest teksty sortować alfabetycznie dzięki tym
tablicom własności określającym też zależności między danymi znakami.
Czysty tekst.
Nie zapisuje Unicode informacji o tym, jak ma być tekst zapisany, nie ma żadnego
formatowania ani nic takiego.
3
Logiczny porządek.
W unicode zawsze zapisujemy informację w takiej kolejności w jakiej jest ona rzeczywiście
pisana, Unicode nie wnika w to czy w języku się pisze od prawej do lewej czy odwrotnie.
Czyli jak piszemy normalnie od prawej to w unicode będzie to zapisane od lewej tak
normalnie ze pierwszy znak od prawej skoro jest pierwszy to będzie zapisany jako pierwszy
z lewej a potem program dba o prawidłowe wyświetlenie tego.
Ujednolicenie.
Identyczne znaki o różnym znaczeniu zastąpiono jednym. Typu przecinek czasami jest
separatorem w liczbie w setkach w jednym języku, separatorem dziesiątek w innym itp. I te
wszystkie przecinki skoro tak samo wyglądają, to mimo że mają różne znaczenie to jest to
wszędzie jeden i ten sam przecinek w unicodzie.
Reprezentacja danych ciąg dalszy:
Przypomnijmy raz jeszcze, że to co się dowiemy jest odmienne od tego jak podchodzi do
tego tematu komputer.
Kodowanie liczb naturalnych
Naturalny zapis wykorzystywany do zapisu liczby w dwójkowym systemie liczbowym. Czyli
12 = 1100 i to jest po prostu 12, a nie +12.
Kodowanie liczb całkowitych
znak-moduł
uzupełnieniowa do dwóch (U2)
Jak chcemy by przy liczbie pojawił się znak, to już jest pewien problem, bo znak też
należy do wartości tej liczby. Ów znak też musimy w jakiś sposób zapisywać. Gdy pojawia
się znak, to istotne jest na ilu bitach będziemy naszą liczbę zapisywać, bo przy różnej ilości
bitów inaczej ta liczba będzie wyglądać. Musimy też ustalać gdzie i w jaki sposób będziemy
znak liczby przechowywać, zazwyczaj umawiamy się, że 0 to jest plus, a 1 to minus i teraz
myślimy na której pozycji ma ten znak występować, byśmy wiedzieli, że właśnie ten bit
odpowiada za znak. Nic nie stoi na przeszkodzie, by znak zapisywać w środkowym bicie, ale
nie ma to większego sensu, zatem zazwyczaj zapisuje się go z jednej ze skrajnych stron i
raczej przyjmuje się, że najstarszy bit czyli pierwszy od lewej strony jest bitem znaku,
wówczas pozostałe bity służą do zapisania naszej liczby jako takiej.
Jak mamy 12=1100 i chcemy ją zapisać w znaku moduł to najpierw ustalamy na ilu
bitach chcemy ją zapisać, umówimy się, że będziemy wykorzystywać wielokrotności 8 bitów.
Mamy zatem powiedzmy do dyspozycji dokładnie 8 bitów, pierwszy z lewej odpowiada za
znak, czyli zostaje 7 bitów na zapisanie wartości bezwzględnej danej liczby. Jak chcemy
zapisać liczbę +12 to zapiszemy ją w ten sposób, że :
0 0001100 i jest to reprezentacja liczby +12 na 8 bitach w reprezentacji znak – moduł
1 0001100 tu chcielibyśmy mieć liczbę -12, ale jak dodamy tak zapisane +12 i -12 to
dostaniemy -24 a nie 0…Wygodna jest dlatego, bo od razu widać, co to za liczba,
jednak jak tylko zaczniemy sprawdzać, to wyjdzie nam, że coś z nią jest nie tak, a
chcemy jednak mieć taki zapis, by chociaż dało się wykonywać na tych liczbach
operacje arytmetyczne.
Dlatego wymyślono reprezentację uzupełnienie do dwóch. Wtedy x zapisany na n bitach ma
taką ładną postać jak poniżej:
Uzupełnienie dwójkowe
Uzupełnieniem dwójkowym liczby x, zapisanej za pomocą n bitów, nazywamy liczbę
xU 2
2n x
Zatem, np. zapiszmy 6=0110 wtedy
4
Xu2=2^4-0110=10000-0110=1010
A pisaliśmy 2^4, bo 4 pozycje zajmuje liczba wyjściowa. Jak teraz sprawdzimy dla y=1010
jego uzupełnienie do 2 to mamy:
Yu2=2^4-1010=10000-1010=0110 czyli jakby dostaliśmy
X=yu2 zatem x=(xu2)u2
Czyli 1010u2= -6 i znów zauważmy, że jakby pierwszy bit od lewej strony jest znakiem
liczby, jak mieliśmy +6 to pierwsze było 0, a jak -6, to pierwszą mieliśmy 1, ale problem
polega na tym, że jak widzimy 1010 to nie widzimy jaka to liczba poza tym, że ujemna, nie
widać, że jest to minus 6. By się dowiedzieć co i jak można spróbować zrobić taką tabelkę:
-8
+4
+2
+1
1
0
1
0
I wyjdzie nam rzeczywiście ładnie -8+2=-6
Czyli dla x dodatniego mamy jakby znak moduł, wszystko jest w porządku.
MUSIMY PAMIĘTAĆ O TYM -8!!!
Można podejść do tego jeszcze inaczej ,mianowicie jak chcemy zamienić 6=0110 to najpierw
negujemy tą liczbę, a potem dodajemy do tego 1 czyli otrzymamy: 1001+1=1010
Jak mamy już jakąś liczbę np. 1011 i chcemy wiedzieć jak to liczba a widzimy, że pierwsza
jest 1 czyli jest ona ujemna, zatem
-8
+4
+2
+1
1
0
1
1
-8+2+1=-5
Lub znów najpierw negujemy a potem odejmujemy? 1.
Znak moduł Uzupełnienie do 2
+5
00000101
00000101
+4
00000100
00000100
+3
00000011
00000011
+2
00000010
00000010
+1
00000001
00000001
+0
00000000
00000000
-0
10000000
-----------1
10000001
11111111
-2
10000010
11111110
-3
10000011
11111101
-4
10000100
11111100
-5
10000101
11111011
Czyli mamy w kodzie uzupełnieniowym tylko jedno 0.
Kodowanie liczb rzeczywistych
zapis stałoprzecinkowy
zapis zmiennoprzecinkowy
zm M 2 zC C
Czyli mówiąc o liczbie rzeczywistej musimy mieć wydzielony jeden fragment na znak,
pewien fragment na część całkowitą i reszta na część ułamkową. Znów musimy najpierw
ustalić na ilu bitach zapisujemy naszą liczbę. Jeśli znów umówimy się na 8 bitów, to pierwszy
odpowiada za znak, np. możemy się umówić, że następne 4 na część całkowitą i zostaną 3
bity na część ułamkową. Jak mamy
0
00111
010 i widzimy od razu, żę jest to liczba dodatnia i łatwo odczytać, że
jest to +3,25 cechą tej notacji jest, że mamy stałą liczbę miejsc przed i po przecinku, czyli
jest to reprezentacja stałoprzecinkowa. Wada jest taka, że czasami mamy np. bardzo duże
liczby całkowite, a innym razem bardzo małe , zatem czasami potrzebujemy wiele miejsca
na część całkowitą, a czasami wieeele na część ułamkową i gdy zapisujemy wciąż tylko
5
liczby bardzo duże, to nie używamy tej części przeznaczonej na część ułamkową, marnujemy
pamięć w ten sposób dlatego fajnie by było mieć możliwość przesuwać ów przecinek i mieć
w ten sposób notację zmiennoprzecinkową. Na kolokwium nie raz pojawia się nagle
zapisanie liczby odwrotnie po to byśmy się nie przywiązywali czyli najpierw do lewej mamy
część ułamkową, potem całkowitą a ostatnia komórka to znak…
Zaletą formatu stałoprzecinkowego jest fakt, że daje nam on stałą precyzję. Jeśli
mamy dwie liczby zapisane w tym formacie i wykonamy na nich operacje arytmetyczne, to
wynik będzie też reprezentowany w tym formacie, co wcale nie jest oczywiste. Najmniejsza
reprezentowana liczba dodatnia w tym formacie to
0
0000 001
= +0,125 i jest to jednocześnie dokładność naszych
obliczeń. Największa liczba dodatnia zapisana w tym formacie to 0
1111
111
=
15,875. Jeśli zaś przesuniemy w ten sposób, że będziemy mieć jedno miejsce na znak, ale
już 6 na część całkowitą i 1 na część ułamkową, to zwiększymy zakres reprezentowanych
liczb do 0
111111
1
=63,5
Ale jednocześnie bardzo spadła nam precyzja do +0,5
Odstęp miedzy wszystkimi reprezentowanymi liczbami w tym formacie jest taki sam, czyli
jak je ustawimy na osi liczbowej to każde dwie sąsiednie będą od siebie w stałej odległości.
Zapis zmiennoprzecinkowy – przykład
Przyjmujemy następujące założenia
wykorzystujemy 8 bitów;
pierwszy bit od lewej (7) oznacza znak liczby;
bity (6-4) oznaczają mantysę;
bity (3-0) oznaczają cechę;
stała KC przyjmuje wartość 7.
Przyjrzyjmy się sposobowi zapisu liczby 1230000000. Ma ona 10 cyfr. Powiedzmy, że
mamy też liczbę 0,0000000123 i na nią również potrzebowalibyśmy w zeszycie w kratkę 10
kratek, ale by dodać te liczby do siebie to już potrzebowalibyśmy kratek 20. Ale możemy też
przecież napisać:
1230000000 = 123 * 10^7
0,0000000123 = 123* 10^-10
Teraz na część jakby całkowitą widać, że potrzebujemy 3 kratki, potem w jednej znak
wykładnika i w dwóch wartość wykładnicza. To jest tzw notacja naukowa. Z tego wywodzi
się zapisywanie liczb w postaci zmiennoprzecinkowej, bo w zależności od wykładnika mamy
przecinek w danym miejscu. Mówiliśmy już, że mamy zapis
z m M 2 z C C , gdzie Pierwsze od prawej C to cecha, obok jest ZC czyli znak cechy,
dalej mamy podstawę systemu w którym liczymy, później mantysa i znak mantysy. Czyli
musimy znaleźć 1 bit na znak mantysy, 1 bit na znak cechy i reszta na resztę, np.
1bit znak mantysy 3 bity
1 bit na znak cechy
3 bity
Zazwyczaj obowiązuje umowa taka, że by była jednoznaczność napisu, to mantysa jest z
przedziału<1,10). W systemie dwójkowym umówieni jesteśmy, że mantysa jest z
przedziału<1,2). AS skoro wiemy, że mantysa zawsze ma na początku 1 to nie
zapamiętujemy jej, bo ta jedynka jest tam zawsze, zapamiętujemy więc tylko część
ułamkową mantysy.
Najmniejsza liczba reprezentowana w tym formacie wygląda tak:
0
000
1
111
Czyli znak jest +, część ułamkowa mantysy to 000 ale przecież mamy mantyse powyżej 1
czyli jest +1.000*2^(-7) = 0,0078125 .
6
A liczba największa w tym formacie to
0 111 0 111
+1,875*2^7= 240
Czyli widać, że zakres liczb w formacie zmiennoprzecinkowym jest znacznie większy niż w
stałoprzecinkowym. Poza tym tu dokładność jest ładna. Ale nie ma tego samego odstępu
między poszczególnymi liczbami wyrażonymi w tym formacie. Ów odstęp zachowuje się tutaj
tak, że blisko zera one są gęste, a potem coraz dalej od siebie. Operacje wykonywane na
tych liczbach bardzo często NIE są wyrażane w tym formacie! Bo np. jak dodamy 17+17 to
nie wyjdzie nam 34 tylko np. 36 bo jak wyjdzie wynik pomiędzy dwoma wartościami to on
zaokrągla bo te wyniki są od siebie w tej a nie innej rosnącej odległości. Dlatego operacje
wykonywane na walutach ZAWSZE są w reprezentacji stałoprzecinkowej.
Komputer też liczy niedokładnie, ale on rezerwuje 32 lub 64 bity i tam siłą rzeczy
dokładność jest większa , bo liczby, których my używamy się na tyle dobrze zagęszczone, że
to działa ;)
W komputerach format zapisu liczby dzieli się zwykle na
Znak mantysa
cecha i wówczas nasz wzór wygląda:
z m M 2C
kC
i wtedy zapisujemy liczbę od 0 do wartości granicznej jaką możemy
zapisać w tej przestrzeni, gdzie Kc to pewna ustalona stała, którą odejmujemy od cechy jak
widać.
7