Pojęcia podstawowe Informatyka dziedzina wiedzy i działalności zajmująca się gromadzeniem, przetwarzaniem i wykorzystywaniem informacji z zastosowaniem środków technicznych (komputerów). Dane wartości określonego typu, opisujące wybrane własności obiektów lub procesów Informacje wyniki gromadzenia i przetwarzania danych, które prowadzą do rozszerzenia wiedzy posiadanej przez odbiorcę Wśród zagadnień składających się na dziedzinę informatyki można wyróżnić: sprzęt służący do obliczeń [1], [2] Literatura: J.Lobur L.Null. The essentials of computer organization and architecture. 3 Ed. Jones and Bartlett Publishers, 2010. W.Stallings. Organizacja i architektura systemu komputerowego. WNT, 2009. metody przetwarzania danych (algorytmy) implementacja tych metod (programowanie) W literaturze zachodniej na określenie tej dziedziny używa się często terminu Computer Science lub Information Technology. 1/40 Pojęcia podstawowe Informatyka jako dziedzina - definicja Computer Science Curricula 2013 Informatyka jest dziedziną nauki i techniki złożoną z czternastu obszarów wyodrębnionych w standardzie nauczania zwanym Computer Science Curricula 2013, opracowanym wspólnie przez IEEE Computer Society i ACM. 2/40 Pojęcia podstawowe Informatyka jako dziedzina - definicja Computer Science Curricula 2013 3/40 Przykładowe systemy Mikrokontrolery z rodziny Arduino 4/40 Przykładowe systemy Mini-komputery - Raspberry Pi i BeagleBone 5/40 Historia rozwoju Generacja zero: mechaniczne maszyny kalkulacyjne (1642–1945) Wilhelm Schickard (1592–1635) jest uważany za twórcę pierwszego mechanicznego kalkulatora, nazwanego Calculating Clock. Mógł on dodawać i odejmować liczby o maksymalnie 6 cyfrach. W 1642 r. Blaise Pascal (1623–1662) zbudował mechaniczny kalkulator nazwany Pascaline aby pomóc swemu ojcu w obliczeniach podatkowych. Pascaline mógł realizować dodawanie z przeniesieniem i odejmowanie. Gottfried Wilhelm von Leibniz (1646–1716), znany matematyk, wynalazł kalkulator o nazwie Stepped Reckoner, który mógł realizować dodawanie, odejmowanie, mnożenie i dzielenie. Charles Babbage (1791–1871) zbudował maszynę różnicową Difference Engine w 1822, która mechanizowała rozwiązywanie wielomianów i właściwie była kalkulatorem, nie komputerem. Babbage zaprojektował też w 1833 r. uniwersalną maszynę liczącą, nazwaną maszyną analityczną (Analytical Engine), która mogła realizować dowolne operacje matematyczne. Analytical Engine posiadała wiele cech wiązanych z nowoczesnymi komputerami: jednostkę arytmetyczno-logiczną do wykonywania obliczeń (Babbage nazywał ją młynem - mill), pamięć (store) i urządzenia wejścia-wyjścia. Babbage zaprojektował też możliwość warunkowego rozgałęzienia programu. Ada Lovelace, córka poety Lorda Byrona, zasugerowała aby Babbage napisał program (plan działania) dla tej maszyny w celu obliczeń liczbowych. Ten fakt jest pierwszym znanym przykładem programu komputerowego, a Ada jest uważana za pierwszego programistę komputerów. Babbage zaprojektował użycie kart perforowanych jako nośnika danych we/wy i programu. Użycie kart dla sterowania działaniem nie pochodziło od Babbage’a, ale od Joseph-Marie Jacquard’a (1752–1834), konstruktora maszyn tkackich. 6/40 Historia rozwoju Generacja 1: komputery lampowe (1945–1953) W latach 1930-tych, Konrad Zuse (1910–1995) kontynuując prace Babbage’a, zastosował układy elektryczne do budowy urządzenia wg projektu Babbage’a. Komputer Zuse’go, nazwany Z1, był zbudowany na przekaźnikach elektromechanicznych zamiast ręcznie napędzanych tarcz stosowanych przez Babbage’a. Komputer Z1 był programowalny i posiadał pamięć, jednostkę arytmetyczną i jednostkę sterującą. Z powodu braku funduszy w Niemczech czasu II wojny światowej, Zuse używał taśmy filmowej w miejsce kart perforowanych jako nośnika danych wejściowych. John Mauchly (1907–1980) i J. Presper Eckert (1929–1995) byli głównymi twórcami komputera ENIAC, wprowadzonego do użytku w 1946 r. ENIAC jest uważany za pierwszy całkowicie elektroniczny, uniwersalny komputer cyfrowy. Maszyna ta używała 17,468 lamp elektronowych, zajmowała 1,800 stóp kw. powierzchni, ważyła 30 ton i zużywała 174 kilowatów mocy. ENIAC miał pamięć o pojemności około 1000 bitów (około 20 10-cyfrowych liczb dziesiętnych) i używał kart perforowanych do zapisu danych. ENIAC był przeznaczony do przyspieszenia procesu obliczenia tablic balistycznych dla artylerii w końcu II wojny światowej. ENIAC był maszyną pracującą w systemie dziesiętnym, nie dwójkowym. To znaczy, że liczby były reprezentowane w formie dziesiętnej i działania arytmetyczne były wykonywane w systemie dziesiętnym. Pamięć składała się z 20 “akumulatorów”, z których każdy mógł przechowywać 10-cio cyfrową liczbę dziesiętną. Główną wadą ENIAC-a była konieczność programowania ręcznego poprzez przełączniki i połączenia przewodami. 7/40 Historia rozwoju ENIAC, 1946 8/40 Historia rozwoju Główne kategorie sprzętu obliczeniowego: Proste maszyny liczące (program sprzętowy), np. maszyna szyfrująca Enigma, używająca wirujących tarcz kodujących, kalkulatory elektroniczne) Uniwersalne komputery, (program ładowany do pamięci). Proces programowania jest ułatwiony przez fakt, że program jest reprezentowany w formie pozwalającej na przechowywanie go w pamięci obok danych. Komputer może pobierać kolejne instrukcje programu z pamięci do wykonania, ponadto program może być modyfikowany przez zmianę wartości zawartych w pamięci. Figure: Sprzętowe i programowe podejście do obliczeń [2] 9/40 Historia rozwoju Architektura von Neumann’a Koncepcja tej architektury (opublikowana przez von Neumann’a w 1945 r.), była oparta na pracach Johna Mauchly i J. Presper Eckert, twórców ENIAC’a. Komputer von Neumann’a składa się z: pamięci przechowującej dane i instrukcje programu jednostki sterującej, która pobiera rozkazy z pamięci, interpretuje je i powoduje ich wykonanie w sposób zależny od wartości danych jednostki arytmetyczno-logicznej (ALU), która wykonuje działania arytmetyczne i inne (logiczne, przesunięcia, itd.) na danych układów wejścia-wyjścia, działających pod kontrolą jednostki sterującej Figure: Architektura von Neumann’a [1] Taki system przesyła wszystkie dane przez jednostkę arytmetyczno-logiczną (dokładnie - przez akumulator, który jest częścią ALU), co jest powodem wąskiego gardła (von Neumann bottleneck). 10/40 Historia rozwoju Zmodyfikowana architektura von Neumann’a Opisana architektura została zoptymalizowana przez wprowadzenie magistral (system bus model). Magistrala danych (data bus) przesyła dane między pamięcią główną a rejestrami procesora (CPU). Magistrala adresowa (address bus) utrzymuje adres danej, która jest przesyłana. Magistrala sterująca (control bus) rozprowadza sygnały sterujące przepływem danych w systemie. Inne ulepszenia podstawowej architektury von Neumann’a to: wykorzystanie rejestrów indeksowych (index registers) do adresowania, obsługa danych zmiennoprzecinkowych (floating point data), użycie przerwań (interrupts) i asynchronicznych operacji wejścia/wyjścia (asynchronous I/O), wprowadzenie pamięci wirtualnej (virtual memory ) i rejestrów ogólnego przeznaczenia (general registers). 11/40 Komputer IAS - pierwszy przykład architektury von Neumann’a Zbudowany w Princeton Institute for Advanced Studies, IAS działa powtarzając wykonywanie cyklu rozkazu. Każdy cykl rozkazu składa się z dwu części: Cyklu pobrania (fetch cycle), w którym kod operacji następnej instrukcji jest ładowany do rejestru IR a pole adresu jest ładowane do rejestru MAR. Instrukcja może być pobrana z rejestru IBR, lub z pamięci poprzez załadowanie słowa do rejestru MBR, a potem do IBR, IR i MAR. Cyklu wykonania, który zaczyna się gdy kod operacji jest w rejestrze IR. Jednostka sterująca interpretuje kod operacji i wykonuje instrukcję, wysyłając odpowiednie sygnały sterujące tak aby przesłać dane lub wykonać działania arytmetyczne w ALU. 12/40 Komputer IAS Zbiór rejestrów Jednostka sterująca i ALU zawierają specjalne komórki pamięci, nazywane rejestrami, o następującym przeznaczeniu: Rejestr buforowy pamięci (Memory buffer register ) (MBR): przechowuje słowo, które ma być zapisane do pamięci lub układu wyjścia, lub słowo które ma być odczytane z pamięci lub układu wejścia. Rejestr adresowy pamięci (Memory address register ) (MAR): przechowuje adres w pamięci słowa, które ma być zapisane z lub odczytane do rejestru MBR. Rejestr rozkazu (Instruction register ) (IR): zawiera 8-bitowy kod operacji instrukcji właśnie wykonywanej. Rejestr buforowy rozkazu (Instruction buffer register ) (IBR): przechowuje tymczasowo prawostronną instrukcję z bieżącego słowa pamięci. Licznik programu (Program counter) (PC): zawiera adres następnej pary instrukcji przeznaczonej do pobrania z pamięci. Akumulator (Accumulator) (AC) i multiplier quotient (MQ): przechowuje tymczasowo argumenty i rezultaty operacji ALU. Na przykład, rezultat mnożenia dwu liczb 40-bitowych jest liczbą 80-bitową; najbardziej znaczące 40 bitów są zapisywane we AC, a najmniej znaczące w MQ. 13/40 Komputer IAS Organizacja pamięci Pamięć komputera IAS składała się z 1000 komórek, zwanych słowami, każde o długości 40 liczb binarnych (bitów). Zarówno program jak i dane były przechowywane w tej pamięci. Liczby i instrukcje były reprezentowane w formie binarnej. Liczby były reprezentowane z użyciem bitu znaku i 39-bitów kodujących wartość. Słowo mogło też przechowywać dwie 20-bitowe instrukcje. Każda z nich składała się z 8-bitowego kodu operacji (opcode) określającego operację do wykonania i 12-bitowego adresu określającego jedno ze słów w pamięci (numerowanych do 0 do 999). Figure: Organizacja pamięci komputera IAS [2] 14/40 Komputer IAS Zbiór instrukcji Komputer IAS miał 21 instrukcji, w 5 grupach: Przesyłanie danych: między pamięcią a rejestrami ALU lub między dwoma rejestrami ALU. Skok bezwarunkowy: Normalnie, jednostka sterująca wykonuje instrukcje kolejno. Aby to zmienić, wykonuje się skok bezwarunkowy (realizacja pętli). Skok warunkowy: rozgałęzienie oparte o warunek, pozwala realizować decyzje. Arytmetyczne: operacje wykonywane przez ALU. Modyfikacja adresu: umożliwia obliczenie nowego adresu i wstawienie go do instrukcji w pamięci. 15/40 Model warstwowy systemu komputerowego Figure: Model warstwowy systemu komputerowego [1] 16/40 Arytmetyka komputerów Dwójkowy system liczbowy - przedstawienie liczb naturalnych System dwójkowy jest systemem pozycyjnym (tak jak dziesiętny), co oznacza, że waga danej cyfry zależy od jej pozycji w liczbie. Liczby naturalne Dla liczby naturalnej A, jej reprezentacja (zwana inaczej rozwinięciem) dana jest zależnością: A = bn−1 ∗ 2n−1 + ... + b1 ∗ 21 + b0 ∗ 20 gdzie bi jest i-tym bitem (cyfrą binarną), a n jest ilością bitów rozwinięcia. Na przykład: liczba dwójkowa 110012 oznacza liczbę dziesiętną 25 = 24 + 23 + 20 17/40 Dwójkowy system liczbowy Liczby całkowite ujemne - reprezentacja znak-moduł Bit znaku poprzedza właściwe bity liczby - jest bitem najbardziej znaczącym. Gdy najbardziej znaczący bit jest równy 0, to liczba jest dodatnia i jej wartość oblicza się ze wzoru: A = bn−2 ∗ 2n−2 + ... + b1 ∗ 21 + b0 ∗ 20 Gdy najbardziej znaczący bit jest równy 1, to liczba jest ujemna i jej wartość oblicza się ze wzoru: A = −(bn−2 ∗ 2n−2 + ... + b1 ∗ 21 + b0 ∗ 20 ) Na przykład: 010010112 = 1 ∗ 26 + 1 ∗ 23 + 1 ∗ 21 + 1 ∗ 20 = 7510 110010112 = −(1 ∗ 26 + 1 ∗ 23 + 1 ∗ 21 + 1 ∗ 20 ) = −7510 Wady tej reprezentacji: Dodawanie i odejmowanie wymagają rozważania zarówno znaków jak i modułów liczb Istnieją dwie reprezentacje liczby 0 (000000002 i 100000002 ) 18/40 Liczby całkowite ujemne Reprezentacja U2 (uzupełnienia do dwóch, czyli podstawy systemu liczbowego) Podobnie jak w reprezentacji znak-moduł, najbardziej znaczący bit jest bitem znaku, tutaj jednak ma wagę 2n−1 i znak ujemny. Dla liczby całkowitej jej przedstawienie w tym kodzie jest dane wzorem: A = −bn−1 ∗ 2n−1 + bn−2 ∗ 2n−2 + ... + b1 ∗ 21 + b0 ∗ 20 Jeśli A jest dodatnie, to bit znaku bn−1 jest zerem. Pozostałe bity reprezentują moduł liczby w identyczny sposób jak w reprezentacji znak-moduł Zero jest traktowane jak wartość dodatnia i dlatego ma bit znaku 0 i moduł złożony z samych zer. Stąd zakres dodatnich liczb całkowitych to [0, 2n−1 − 1] , czyli dla n=8 zakres ten to [0, 127] (z wartością maksymalną gdy wszystkie bity modułu są 1). Większe liczby wymagają więcej bitów w słowie Dla liczb ujemnych bit znaku bn−1 jest 1. Pozostałe n-1 bity określają dowolną z 2n−1 wartości, stąd zakres tych liczb to [−2n−1 , −1], czyli dla n=8 zakres ten to [−128, −1] Zalety reprezentacji U2: zapewnia jednolitą realizację dodawania i odejmowania, dlatego jest powszechnie używana jako reprezentacja liczb całkowitych w większości procesorów brak podwójnej reprezentacji zera, stąd zwiększony o 1 zakres liczb możliwych do przedstawienia 19/40 Liczby całkowite ujemne U2 - przykład, Konwersja liczb binarnych dla różnych długości słów Na przykład: 010010112 = 1 ∗ 26 + 1 ∗ 23 + 1 ∗ 21 + 1 ∗ 20 = 7510 101101012 = −1 ∗ 27 + 1 ∗ 25 + 1 ∗ 24 + 1 ∗ 22 + 1 ∗ 20 = −7510 Konwersja liczb binarnych dla różnych długości słów Jeśli należy rozszerzyć ilość bitów liczby z n do m, (przy czym n < m) to: Dla reprezentacji znak-moduł należy przesunąć bit znaku do najdalszej lewej pozycji, a pozostałe wolne bity wypełnić zerami Dla reprezentacji uzupełnienia do dwóch należy przesunąć bit znaku do najdalszej lewej pozycji, a pozostałe wolne bity wypełnić kopiami bitu znaku (dla liczb dodatnich wypełnia się zerami, dla liczb ujemnych – jedynkami). 20/40 Konwersja między systemami dziesiętnym i binarnym Konwersja dziesiętnej liczby całkowitej dodatniej Konwersja z postaci binarnej na dziesiętną jest prosta i wynika bezpośrednio z rozwinięcia Konwersja liczby całkowitej dodatniej z postaci dziesiętnej na binarną jest wykonywana metodą dzielenia przez 2. Jeśli mamy liczbę dziesiętną N to po podzieleniu jej przez 2 otrzymujemy iloraz N1 oraz resztę r1 , zgodnie z zależnością: N = 2 ∗ N1 + r1 , gdzie r1 jest 0 lub 1 Następnie dzielimy iloraz N1 przez 2, otrzymując nowy iloraz N2 oraz resztę r2 : N1 = 2 ∗ N2 + r2 , gdzie r2 jest 0 lub 1 Stąd: N = 2 ∗ (2 ∗ N2 + r2 ) + r 1 = 22 ∗ N2 + 21 ∗ r2 + 20 ∗ r1 Ponieważ N > N1 > N2 ..., postępujemy tak dalej aż do otrzymania ilorazu Nk = 1 i reszty rk równej 0 lub 1. Algorytm konwersji z postaci dziesiętnej na binarną Konwersja jest wykonywana metodą dzielenia przez 2. Kolejne reszty rk i ostatni iloraz Nk = 1 dają cyfry binarne w kolejności rosnącego znaczenia. Czy to znaczy, że zawsze MSB (najbardziej znaczący bit) jest równy 1? NIE, to zależy od przyjętej długości słowa: kiedy jest dłuższe niż trzeba dla danej liczby, pozostałe bity będą zerami. 21/40 Konwersja między systemami dziesiętnym i binarnym Konwersja dziesiętnej liczby całkowitej dodatniej - przykłady 1310 = 11012 13 : 2 = 6 r 1 6: 2=3r0 3: 2=1r1 1610 = 100002 16 : 8: 4: 2: 2=8r0 2=4r0 2=2r0 2=1r0 22/40 Konwersja między systemami dziesiętnym i binarnym Konwersja dziesiętnej liczby całkowitej ujemnej Aby przekształcić liczbę całkowitą ujemną do postaci binarnej należy: 1 wykonać konwersję liczby dodatniej o tym samym module 2 zanegować ją (patrz poniżej): Dla reprezentacji znak-moduł negowanie sprowadza się do odwrócenia bitu znaku. Dla reprezentacji uzupełnienia do dwóch należy wziąć uzupełnienie Boole’a każdego bitu liczby (łącznie z bitem znaku) i traktując wynik jako liczbę całkowitą bez znaku dodać 1. UWAGA: występują tu dwa przypadki szczególne, które muszą być odpowiednio traktowane: 1 A = 0. Wtedy A = 000000002 w reprezentacji U2. Uzupełnienie bitowe 111111112 . Po dodaniu do niego 1 otrzymujemy przeniesienie, które jest ignorowane, tak więc w rezultacie otrzymujemy poprawny wynik negacji zera równy zero. 2 Negowanie wzoru bitowego złożonego z 1 z następującymi n - 1 zerami daje w wyniku tę samą liczbę. Na przykład: −12810 = 100000002 . Uzupełnienie bitowe = 011111112 . Po dodaniu do niego 1 otrzymujemy 100000002 = −12810 . Problem powstaje, ponieważ 12810 nie może być reprezentowane na 8 bitach. 23/40 Arytmetyka liczb całkowitych Dodawanie Przy przyjętej długości słowa, możemy otrzymać wynik większy niż dopuszczalny – występuje wtedy tzw. przepełnienie. Taki przypadek jest odpowiednio sygnalizowany przez ALU i wynik operacji jest odrzucany. Reguła przepełnienia Jeśli są dodawane dwie liczby dodatnie lub dwie ujemne, to przepełnienie występuje wtedy i tylko wtedy, gdy wynik ma znak przeciwny W pewnych warunkach może wystąpić tzw. przeniesienie - poza końcem słowa pojawia się bit, który musi być ignorowany. 24/40 Dwójkowy system liczbowy Dodawanie liczb całkowitych - przykłady (-7) + (+5) = (-2) 1001 0101 —— 1110 = -2 (-4) + (+4) = (0) 1100 0100 ——— 10000 przeniesienie, bit ignorowany 0000 = 0 (+4) + (+5) = (?) 0100 0101 ——— 1001 przepełnienie, zgodnie z regułą: wynik jest ujemny, a oba argumenty dodatnie (-4) + (-1) = (-5) 1100 1111 ——— 11011 przeniesienie, bit ignorowany 1011 = -5 25/40 Arytmetyka liczb całkowitych Odejmowanie Reguła odejmowania W celu realizacji odjęcia od jednej liczby (odjemnej) drugiej liczby (odjemnika) należy dodać do odjemnej uzupełnienie do dwóch odjemnika. 26/40 Arytmetyka liczb całkowitych Odejmowanie - przykłady (5) - (2) = (3) (2) - (7) = (-5) M = 210 = 00102 S = 710 = 01112 -> −710 = 10012 0010 +1001 ——— 1011 = -5 M = 510 = 01012 S = 210 = 00102 -> −210 = 11102 0101 +1110 ——— 10011 przeniesienie, bit ignorowany 0011 = 3 (-6) - (4) = (?) (-5) - (2) = (-7) M = −610 = 10102 S = 410 = 01002 -> −410 = 11002 1010 +1100 ——— 10110 przeniesienie, bit ignorowany 0110 przepełnienie M = −510 = 10112 S = 210 = 00102 -> −210 = 11102 1011 +1110 ——— 11001 przeniesienie, bit ignorowany 1001 = -7 27/40 Arytmetyka liczb całkowitych Podsumowanie Reprezentacje analizowane dotąd można nazwać stało-pozycyjnymi - położenie przecinka pozycyjnego (binarnego) jest ustalone i z założenia znajduje się on na prawo od cyfry położonej najdalej na prawo. Można używać tej samej reprezentacji dla ułamków binarnych, posługując się skalowaniem liczb, tak że przecinek binarny znajdzie się w innym, wybranym położeniu. 28/40 Liczby ułamkowe i rzeczywiste Wymagają one reprezentacji bardziej rozbudowanej. Istnieją dwie jej odmiany: stałoprzecinkowa, gdzie ustala się położenie przecinka binarnego w pewnym miejscu, a więc przeznacza się ustaloną liczbę bitów na część całkowitą i ułamkową liczby. Np., jeśli na część całkowitą przeznaczy się n+1 bitów, a na część ułamkową k bitów, to reprezentacja jest dana zależnością: A = (−2 ∗ bn + 1) ∗ (bn−1 ∗ 2n−1 + ... + b1 ∗ 21 + b0 ∗ 20 + +b−1 ∗ 2−1 + ... + b−k ∗ 2−k ) Podejście to ma ograniczenia: nie mogą być reprezentowane ani bardzo duże liczby, ani bardzo małe ułamki. Ponadto, ułamkowe składniki ilorazu przy dzieleniu dużych liczb mogą być utracone. zmiennoprzecinkowa, gdzie używa się notacji naukowej w formie: ±S ∗ B E gdzie S jest mantysą, B jest podstawą systemu liczbowego (10 dla dziesiętnego, 2 dla binarnego), a E jest wykładnikiem. Na przykład, systemie dziesiętnym: 31415000000010 może być reprezentowane jako 0.31415 ∗ 1012 0.0000003141510 może być reprezentowane jako 0.31415 ∗ 10−6 . W tym podejściu przesuwa się przecinek dziesiętny do zadanego położenia i używa wykładnika do pamiętania położenia tego przecinka. 29/40 Liczby ułamkowe i rzeczywiste Notacja zmiennoprzecinkowa Takie samo podejście może być stosowane do liczb binarnych. Mogą one być przechowywane w postaci słowa binarnego o trzech polach zawierających: znak (plus lub minus), mantysę S i wykładnik E (podstawa jest ustalona i nie musi być przechowywana). Typowy 32-bitowy format zmiennoprzecinkowy: Lewy bit reprezentuje znak liczby (0 – dodatnia, 1 – ujemna). Wartość wykładnika jest przechowywana w bitach 23-30, w postaci reprezentacji przesuniętej (ustalona wartość przesunięcia jest odejmowana od pola w celu otrzymania prawdziwej wartości wykładnika). Tu na 8 bitach przechowuje się liczby z zakresu 0-255; po odjęciu przesunięcia równego 128, prawdziwe wartości wykładnika mieszczą się w zakresie –128 do +127. Mantysa jest zwykle tak obliczona, że cała liczba jest znormalizowana, co upraszcza operacje. Liczba znormalizowana ma postać: ±0.1bbb...b ∗ 2E , gdzie b jest dowolną cyfrą binarną. Wynika z tego, że lewy bit mantysy ma zawsze wartość 1, w związku z tym nie trzeba go przechowywać, a mantysa ma wartość z przedziału [0.5, 1.0). 30/40 Liczby ułamkowe i rzeczywiste Notacja zmiennoprzecinkowa Opisany format pozwala na przedstawienie liczb z zakresów: ujemnych (−(1 − 2−24 ) ∗ 2127 , −0.5 ∗ 2−128 ) (−1.7 ∗ 1038 , −1.47 ∗ 10−39 ) dodatnich (0.5 ∗ 2−128 , (1 − 2−24 ) ∗ 2127 ) (1.47 ∗ 10−39 , 1.7 ∗ 1038 ) Powyższe zakresy nie obejmują pięciu obszarów: liczb ujemnych < −(1 − 2−24 ) ∗ 2127 (przepełnienie ujemne) liczb ujemnych > −0.5 ∗ 2−128 liczb dodatnich < 0.5 ∗ 2−128 liczb dodatnich > (1 − 2−24 ) ∗ 2127 (niedomiar ujemny) (niedomiar dodatni) (przepełnienie dodatnie) zera, które jest opisywane specjalnym wzorem bitowym. Przepełnienie pojawia się, gdy wynik operacji arytmetycznej przekracza co do modułu wartość, która może być wyrażona przez wykładnik równy 127. Niedomiar pojawia się, gdy moduł części ułamkowej jest za mały. Niedomiar jest mniejszym problemem, ponieważ rezultat może być zwykle przybliżony zerem. Dodatkowo, liczby zmiennoprzecinkowe nie są równomiernie rozłożone na osi liczbowej (jak stałoprzecinkowe). Ich gęstość jest największa w okolicy początku osi, a dalej maleje. Dlatego w wielu przypadkach obliczenia są obarczone błędami zaokrągleń. 31/40 Liczby ułamkowe i rzeczywiste Standard IEEE dla liczb zmiennoprzecinkowych Najważniejszy standard reprezentacji liczb zmiennoprzecinkowych - norma IEEE 754. Została ona stworzona by: Ułatwić przenoszenie programów między różnymi procesorami Umożliwić rozwój oprogramowania wymagającego intensywnych obliczeń numerycznych. Standard ten definiuje format 32-bitowy (pojedyncza precyzja) i 64-bitowy (podwójna precyzja), odpowiednio przy 8 i 11 bitowych wykładnikach. Dodatkowo, standard definiuje 2 formaty rozszerzone (też pojedynczej i podwójnej precyzji), których format jest zależny od implementacji. Formaty rozszerzone wprowadzają dodatkowe bity dla wykładnika i mantysy (zwanej fraction). UWAGA: nie wszystkie wzory bitowe są interpretowane w zwykły sposób – niektóre z nich oznaczają specjalne wartości: zerowy wykładnik wraz z zerowym ułamkiem oznacza dodatnie lub ujemne zero, zależnie od bitu znaku zerowy wykładnik wraz z niezerowym ułamkiem oznacza liczbę nienormalizowaną wykładnik o samych jedynkach wraz z zerowym ułamkiem oznacza dodatnią lub ujemną nieskończoność, zależnie od bitu znaku wykładnik o samych jedynkach wraz z niezerowym ułamkiem oznacza NaN (not a number), wartość używaną do sygnalizacji różnych sytuacji wyjątkowych napotkanych w obliczeniach. 32/40 Liczby ułamkowe i rzeczywiste Konwersja z postaci dziesiętnej na binarną stałoprzecinkową Dla reprezentacji stałoprzecinkowej konwersja jest wykonywana oddzielnie dla części całkowitej i ułamkowej liczby: 1 Konwersja dla części całkowitej jest wykonywana jak dla liczby całkowitej w reprezentacji znak-moduł Konwersja dla części ułamkowej polega na wykonywaniu mnożenia przez 2. W kolejnych krokach ułamkowa część liczby dziesiętnej jest mnożona przez 2 i cyfra znajdująca się na lewo od przecinka w iloczynie (równa 0 lub 1) wchodzi w skład reprezentacji binarnej począwszy od najbardziej znaczącego bitu. Część ułamkowa iloczynu jest używana jako mnożna w następnym kroku. Na przykład: 0, 2510 = 00, 012 2 Obliczanie: 1 0,25 * 2 = 0,5 -> .0 2 0,5 * 2 = 1,0 -> .01 UWAGA: Proces ten nie zawsze jest dokładny; ułamek dziesiętny o skończonej liczbie cyfr może wymagać ułamka binarnego o nieskończonej lub większej niż dopuszczalna liczbie cyfr. 33/40 Liczby ułamkowe i rzeczywiste Konwersja z postaci dziesiętnej na binarną stałoprzecinkową Na przykład: 0, 25510 = 00, 010000012 Obliczanie: 1 0,255 * 2 = 0,510 -> .0 2 0,510 * 2 = 1,020 -> .01 3 0,020 * 2 = 0,040 -> .010 4 0,040 * 2 = 0,080 -> .0100 5 0,080 * 2 = 0,160 -> .01000 6 0,160 * 2 = 0,320 -> .010000 7 0,320 * 2 = 0,640 -> .0100000 8 0,640 * 2 = 1,280 -> .01000001 Jaki jest błąd reprezentacji tej liczby ? Wartość = 1 ∗ 2−2 + 1 ∗ 2−8 = 0, 25 + 0, 0039 = 0, 2539 Błąd = 0,255 - 0,2539 = 0,0011 = 0,43 % 34/40 Liczby ułamkowe i rzeczywiste Konwersja z postaci dziesiętnej na 32-bitową zmiennoprzecinkową Na przykład: 0, 25510 = 001111111000001010001111010111002 1 2 3 4 5 Ustawić wartość wykładnika E na 0. Sprowadzić metodą dzielenia lub mnożenia przez 2, liczbę do zakresu [0.5, 1.0). Po każdej operacji dzielenia zwiększać wartość E o 1, przy każdej operacji mnożenia zmniejszać wartość E o 1. W wyniku tego otrzymuje się wartość mantysy, którą należy zakodować bitami 0-22, pamiętając że bit na prawo od przecinka binarnego nie jest zapisywany. Dokonać konwersji mantysy obliczonej w kroku 2 z postaci dziesiętnej do binarnej jak dla reprezentacji stałoprzecinkowej o zerowej liczbie cyfr binarnych przed przecinkiem binarnym i 24 bitami po przecinku. W celu otrzymania wykładnika w reprezentacji przesuniętej, dodać do jego wartości obliczonej w kroku 2 wartość 128. Jeśli wartość liczby jest ujemna, ustawić bit numer 31 na 1, w przeciwnym razie na 0. Obliczanie: 1 E = 0 2 0, 255 ∗ 2 = 0, 510 → E = E − 1 3 S = 1000001010001111010111002 4 E = E + 128 = 12710 = 011111112 5 b31 = 0 6 Wynik: 0 01111111 000 0010 1000 1111 0101 1100 35/40 Notacja szesnastkowa Jest ona używana w celu bardziej wygodnej reprezentacji zewnętrznej liczb binarnych, tzn. poza systemem komputerowym (wyświetlania lub drukowania zawartości pamięci, plików, itp). W tej notacji, liczby binarne są grupowane czwórkami. Dla każdej możliwej kombinacji 4 bitów istnieje symbol, począwszy od 0 do 9 i od A do F. Te 16 symboli to cyfry szesnastkowe. Stąd ciąg cyfr szesnastkowych można traktować jako wartość całkowitą przy podstawie równej 16. Ciąg ten jest zapisywany z literą ’H’ na końcu dla zaznaczenia podstawy stosowanego systemu liczbowego. Na przykład: 2F16 = 216 ∗ 161 + F16 ∗ 160 = 210 ∗ 161 + 1510 ∗ 160 = 47 Notacja szesnastkowa jest używana nie tylko do wygodnego przedstawiania liczb całkowitych, ale również innych danych binarnych (tekstowych, liczbowych, itp.). Powody jej stosowania: Bardziej zwarta niż binarna Większość komputerów używa słów o długości będącej wielokrotnością 4 bitów Łatwość konwersji między systemem binarnym i szesnastkowym. 36/40 Inne reprezentacje danych dziesiętnych BCD, Packed decimal Pomimo że wewnątrz komputera operacje realizuje się w systemie binarnym, zwykli użytkownicy preferują zapis dziesiętny. W związku z tym istnieje potrzeba przekształcenia na wejściu z postaci dziesiętnej na binarną, a na wyjściu - odwrotnie. Dla aplikacji wymagających dużego nakładu operacji we/wy i stosunkowo małego udziału obliczeń, właściwe jest stosowanie systemu dziesiętnego dla zapisu, odczytu i przetwarzania. Podstawową reprezentacją jest BCD (binary-coded decimal), która jest klasą binarnych sposobów kodowania danych dziesiętnych, w której każda cyfra dziesiętna jest zapisana przy użyciu 4 bitów. Więc 0 = 0000, 1 = 0001, 8 = 1000, a 9 = 1001. Specjalne ciągi bitów są stosowane dla zapisu znaku (używa się cyfry znaku równej 1100 dla dodatnich wartości i 1101 dla ujemnych). Zapis BCD jest dość rozrzutny, ponieważ wykorzystuje tylko 10 z 16 możliwych wartości 4-bitowego słowa. Typową reprezentacją jest packed decimal, w której dwie cyfry dziesiętne liczby upakowuje się w bajcie. Aby zapisać liczby wielocyfrowe, łączy się odpowiednią ilość bajtów. Tak więc, kod liczby 246 to 0000 0010 0100 0110. Znacząco mniejsza gęstość zapisu niż osiągana w systemie binarnym jest kompensowana przez brak konieczności konwersji i - co czasami ważniejsze - brak zaokrągleń. Np. wartość 0.2 może być reprezentowana dokładnie w kodzie BCD (jako 0.0010), ale ma nieskończone rozwinięcie binarne (.001100110011...). Wiele maszyn (starsze: VAX, microVAX, nowsze: Intel x86 (32-bit), IBM POWER7) zapewnia specjalne instrukcje arytmetyczne wykonujące operacje bezpośrednio na danych dziesiętnych upakowanych. Algorytmy są bardzo podobne do wcześniej dyskutowanych, ale muszą obsługiwać przeniesienie dziesiętne. Implementacje programowe: Intel Decimal Floating-Point Math Library (2011) 37/40 Reprezentacja znaków ASCII Dotąd dyskutowane reprezentacje stosowane są do działań na liczbach wewnątrz komputera. W celu prezentacji ich w postaci zrozumiałej dla człowieka, należy dokonać ich przekształcenia do postaci tekstowej lub graficznej. Stosuje się w tym celu standardy takie jak: ASCII i UNICODE. ISO opracowała 7-bitowy schemat kodowania zwany International Alphabet Number 5. W 1967 r. wprowadzono standard pochodny, nazwany ASCII. American Standard Code for Information Interchange ASCII definiuje kody dla 32 znaków sterującyh, 10 liczb, 52 liter (małych i wielkich), 32 znaków specjalnych (jak np. @) i znaku odstępu. Najstarszy (ósmy) bit był przeznaczony do kontroli parzystości. Parzystość jest najprostszym ze sposobów detekcji błędów. Bit parzystości jest zerem lub jedynką w zależności od tego czy wartość sumy pozostałych bitów jest parzysta/nieparzysta. Na przykład, jeśli stosuje się kontrolę parzystości (even parity ) przesyłając znak ASCII A, najniższe 7 bitów to 100 0001. Ponieważ ich suma jest parzysta, bit parzystości będzie równy 0 i cały kod ASCII będzie równy 0100 0001. Podobnie, przy transmisji znaku ASCII C, 100 0011, bit parzystości będzie równy 1, stąd przesyłana wartość to 1100 0011. Parzystość może być używana tylko do detekcji błędów pojedynczych bitów. 38/40 Reprezentacja znaków ASCII W miarę jak komputery stawały się bardziej stabilne, potrzeba stosowania bitu parzystości malała. W początkach lat 1980-tych, producenci mikrokomputerów zaczęli używać bitu parzystości do rozszerzenia zakresu reprezentowanych znaków (extended character set) przez kody z zakresu 12810 do 25510 . W zależności od standardu, rozszerzone zestawy znaków mogą reprezentować symbole matematyczne, znaki alfabetów narodowych lub inne symbole. ISO/IEC 8859-2, również znane jako Latin-2, bądź "środkowo–" i "wschodnioeuropejskie", jest drugą częścią standardu kodowania znaków zdefiniowanego przez organizację ISO. Tablica kodów ISO/IEC 8859-2, zawierająca m.in. polskie znaki diakrytyczne. 39/40 Reprezentacja znaków Unicode Unicode jest 16-bitowym alfabetem, który jest zgodny wstecznie z ASCII i Latin-1. Jest też zgodny z definicją międzynarodowego alfabetu ISO/IEC 10646-1. Ponieważ podstawowe kodowanie w Unicode jest 16 bitowe, ma on wystarczającą pojemność dla zapisu większości znaków spotykanych we wszystkich językach świata. Dodatkowo, Unicode definiuje mechanizm rozszerzania, który pozwala zakodować milion innych znaków. Jest to wystarczające do reprezentowania znaków wszystkich języków używanych w historii cywilizacji. Unicode jest domyślnym systemem kodowania w języku programowania Java, XML i pochodnych. Cytat ze strony internetowej Unicode Consortium: Zasadniczo, komputery operują na liczbach. Przechowują one litery i inne znaki, poprzez przypisaną do nich liczbę (kod znaku). Przed wprowadzeniem systemu kodowania Unicode, istniały setki różnych systemów kodowania, przyporządkowujących kod do znaku. Nie istniał system kodowania, wystarczająco pojemny dla wszystkich potrzebnych znaków: na przykład, Unia Europejska potrzebuje wielu różnych systemów kodowania do obsługi wszystkich oficjalnych języków. Nawet dla samego języka angielskiego potrzebnych było kilku systemów kodowania dla zapisu liter, interpunkcji i symboli technicznych będących w użyciu. Te systemy kodowania często kolidowały ze sobą, tzn. dwa systemy używały tego samego kodu znaku dla dwu różnych znaków, lub różnych kodów dla tego samego znaku. W tej sytuacji komputery (w szczególności serwery) musiały obsługiwać wszystkie te systemy; a w czasie przenoszenia danych dochodziło do ich przekłamania. 40/40