Wprowadzenie do inżynierii przetwarzania informacji. Ćwiczenie 3
Transkrypt
Wprowadzenie do inżynierii przetwarzania informacji. Ćwiczenie 3
Wprowadzenie do inżynierii przetwarzania informacji. Ćwiczenie 3. Arytmetyka stałopozycyjna Cel dydaktyczny: Nabycie umiejętności wykonywania podstawowych operacji arytmetycznych na liczbach stałopozycyjnych. Algorytmy dodawania, odejmowania, mnożenia i dzielenia pisemnego w kodzie NKB. Wykonywanie operacji arytmetycznych w systemach cyfrowych. Operacje arytmetyczne w kodzie BCD i kodach uzupełnieniowych. Algorytmy mnożenia i dzielenia w systemach cyfrowych. 1. Odjąć pisemnie liczby binarne w kodzie NKB o wartościach A = 14.5 i B = 7.625. 2. Pomnożyć pisemnie liczby binarne w kodzie NKB o wartościach A = 13.25 i B = 5. 3. Podzielić pisemnie liczby binarne w kodzie NKB o wartościach A = 19.75 i B = 4.125. Wyznaczyć iloraz i resztę. 4. Dodać w kodzie NKB oraz kodzie BCD następujące liczby binarne 8-bitowe o wartościach A = 94 i B = 28. 5. Odjąć w kodzie ZM liczby binarne 8-bitowe o wartościach A = +12 i B = -25. 6. Dodać w kodzie U1 liczby binarne 8-bitowe o wartościach A = -13 i B = 46. 7. Dodać w kodzie U1 liczby binarne 8-bitowe o wartościach A = -25 i B = -99. 8. Dodać w kodzie U2 liczby binarne 9-bitowe o wartościach A = -35 i B = -135. 9. Wykonać mnożenie w kodzie NKB za pomocą algorytmu przeznaczonego dla układów cyfrowych. Pomnożyć 5-bitowe liczby binarne A = 01101 = +13 i B = 01001 = +9. Przyjąć wynik 10-bitowy. 10. Wykonać dzielenie w kodzie NKB za pomocą algorytmu przeznaczonego dla układów cyfrowych. Podzielić liczbę 8-bitową A = 0011 1000 = +56 przez liczbę 4-bitową B = 0110 = +6. Wprowadzenie do inżynierii przetwarzania informacji. Ćwiczenie 3. Arytmetyka stałopozycyjna Cel dydaktyczny: Nabycie umiejętności wykonywania podstawowych operacji arytmetycznych na liczbach stałopozycyjnych. Algorytmy dodawania, odejmowania, mnożenia i dzielenia pisemnego w kodzie NKB. Wykonywanie operacji arytmetycznych w systemach cyfrowych. Operacje arytmetyczne w kodzie BCD i kodach uzupełnieniowych. Algorytmy mnożenia i dzielenia w systemach cyfrowych. Wprowadzenie teoretyczne 3. Operacje na liczbach stałopozycyjnych Na liczbach rzeczywistych zapisanych w układzie binarnym można wykonywać podstawowe operacje arytmetyki stałopozycyjnej podobnie jak w układzie dziesiętnym. 3.1. Reguły działań arytmetycznych w układzie dziesiętnym Dodawanie Operacja dodawania dwóch liczb S = A+B w układzie dziesiętnym rozpoczyna się od cyfr najmniej znaczących ai oraz bi obu liczb. Jeśli suma cyfr przekroczy 9 pojawia się przeniesienie ci+1=1 na następną pozycję, a jeśli nie to otrzymana suma stanowi najmniej znaczącą cyfrę wyniku. Wynika stąd, że w przypadku dodawania cyfr ai oraz bi należy uwzględnić przeniesienie wchodzące ci z pozycji mniej znaczącej oraz przeniesienie wychodzące ci+1 na pozycję bardziej znaczącą. W przypadku dodawania wartość przeniesienia nie może przekroczyć jedynki. Reguły dodawania cyfr w układzie dziesiętnym mogą być zapisane w postaci: si = (ai + bi + ci) mod 10, ci+1 = (ai + bi + ci) div 10, gdzie mod – operator reszta z dzielenia, div – operator część całkowita z dzielenia. W wyniku dodawania liczb n-cyfrowych może pojawić się wynik co najwyżej (n+1) cyfrowy. Przykład. 3.1. Dodać pisemnie liczby dziesiętne A = 244 i B = 58. 11 244 +58 ---302 Suma S = A + B = 244 + 58 = 302. Odejmowanie Wyznaczanie różnicy cyfr ai - bi może wymagać pobrania pożyczki z pozycji bardziej znaczącej (i+1). Jeśli między dwoma odejmowanymi cyframi zachodzi relacja ai < bi, to pobierana jest pożyczka z pozycji (i+1). Jej wartość na pozycji i wynosi 10. Stąd, di = (10 + ai) bi, natomiast cyfra ai+1 > 0 przyjmuje wartość równą (ai+1-1). W przypadku odejmowania można przyjąć, że A ≥ B. Wówczas różnica jest dodatnia i wynosi D = A-B. W przeciwnym przypadku należy obliczyć D = B-A i wynik wziąć ze znakiem przeciwnym. Przykład. 3.2. Odjąć pisemnie liczby dziesiętne A = 143 i B = 97. 3 10 1 4 3 -9 7 ------4 6 Różnica D = A - B = 143 - 97 = 46. Mnożenie W przypadku mnożenia dwóch cyfr ai oraz bi może pojawić się przeniesienie wychodzące ci+1 na pozycję bardziej znaczącą o wartości większej niż jeden. Uwzględniając przeniesienie z pozycji mniej znaczącej reguły obliczania iloczynu M = A*B w układzie dziesiętnym można zapisać w postaci: mi = (ai * bi + ci) mod 10, ci+1 = (ai * bi + ci) div 10. W wyniku mnożenia liczby k-cyfrowej przez liczbę n-cyfrową może pojawić się iloczyn złożony z co najwyżej (k+n) cyfr. Przykład. 3.3. Pomnożyć pisemnie liczby dziesiętne A = 453 i B = 37. 1 32 453 *37 ---3171 +1359 ------16761 Iloczyn M = A * B = 453 * 37 = 16761. W wyniku mnożenia liczby 3-cyfrowej przez liczbę 2-cyfrową otrzymano 5-cyfrowy iloczyn. Dzielenie Operacja dzielenia dwóch liczb E = A : B jest równoważna odejmowaniu A – B. Jeśli A ≥ B, to można wyznaczyć część całkowitą z dzielenia oraz resztę lub część całkowitą i część ułamkową z zadaną dokładnością (ustalona liczba cyfr po przecinku ilorazu). Wynika stąd, że iloraz można obliczyć jedynie z zadaną dokładnością lub podać wynik w postaci ułamka. Przykład. 3.4. Podzielić pisemnie liczby dziesiętne A = 1121 i B = 37. 30 ---1121 : 37 -111 ---11 Iloraz E = A : B = 1121 : 37 = 30 i 11/37, tj. iloraz wynosi trzydzieści i jedenaście trzydziestych siódmych. Dzielenie można wykonywać z uwzględnieniem zadanej liczby miejsc po przecinku. 30.297 2... ---1121 : 37 -111 ---110 -74 ---360 -333 ----270 -259 ----110 -74 ---... W wyniku dzielenia E = 30.297 (297) ... . 3.2. Operacje arytmetyczne w naturalnym kodzie binarnym (NKB) Reguły działań arytmetycznych w układzie binarnym są podobne do reguł stosowanych w układzie dziesiętnym. Różnica polega na tym, że operacje dodawania cyfr wykonuje się modulo dwa, a w przypadku odejmowania pożyczka z pozycji bardziej znaczącej ma wartość dwa na pozycji mniej znaczącej. Poniżej są przedstawione reguły pisemnego dodawania, odejmowania, mnożenia i dzielenia dla liczb jednobitowych w kodzie NKB. 3.2.1. Dodawanie binarne W przypadku dodawania składników jednobitowych ai + bi są możliwe cztery przypadki. Cyfra ai może być równa 0 lub 1 i podobnie cyfra bi. Prowadzi to do następujących reguł dodawania składników jednobitowych. Przeniesienie ci+1 0 1 0 0 ---------------------------------------Składnik ai 1 1 0 0 Składnik bi 0 1 0 1 ---------------------------------------Suma si 1 0 0 1 Przykład. 3.5. Dodać pisemnie liczby binarne A = 1101.11 = 13.75 i B = 110.1 = 6.5. 1111 1101.11 +110.1 --------10100.01 S = A + B = 1101.11 + 110.1 = 10100.01 = 20.25. Sprawdzenie: 13.75 + 6.5 = 20.25. 3.2.2. Odejmowanie binarne Operacja odejmowania binarnego liczb jednobitowych ai - bi może wymagać zaciągnięcia pożyczki z pozycji bardziej znaczącej. Uwzględniając dopuszczalne wartości bitów oraz to, że pożyczka ma wartość dwa, reguły odejmowania binarnego liczb jednobitowych mają następującą postać: 0 0 0 1 Pożyczka pi+1 ---------------------------------------Odjemna ai 1 1 0 0 0 1 0 1 Odjemnik bi ---------------------------------------Różnica di 1 0 0 1 W przypadku odejmowania 0 – 1 pobierana jest pożyczka o wartości jeden z pozycji (i+1). Wartość pożyczki na pozycji o numerze (i) wynosi 2. Stąd, różnica ai - bi = 0 + 2 – 1 = 1. Podczas odejmowania liczb binarnych A – B wystarczy zakładać, że A ≥ B, gdyż w przeciwnym przypadku można wykonać odejmowanie B – A i następnie wynik końcowy wziąć ze znakiem przeciwnym. Przykład. 3.6. Odjąć pisemnie liczby binarne A = 1001.01 = 9.25 i B = 110.1 = 6.5. 0120 2 1001.01 -110.10 --------010.11 D = A - B = 1001.01 - 110.1 = 10.11 = 2.75. Sprawdzenie: 9.25 - 6.5 = 2.75. 3.2.3. Mnożenie binarne Mnożenie cyfr binarnych ai * bi nie prowadzi do powstania przeniesienia na pozycję bardziej znaczącą. Stąd, reguły mnożenia mają następującą postać: Mnożna ai 1 1 0 0 Mnożnik bi 0 1 0 1 ---------------------------------------Iloczyn mi 0 1 0 0 W przypadku mnożenia liczb w układzie binarnym zachodzi konieczność sumowania iloczynów cząstkowych. W wyniku mnożenia może pojawić się iloczyn zajmujący tyle bitów ile wynosi suma bitów zajmowanych przez mnożną i mnożnik. Jeśli mnożone liczby są ułamkami, to podczas mnożenia można pominąć przecinki w mnożnej i mnożniku, a następnie wstawić przecinek w otrzymanym iloczynie. Liczba bitów po przecinku w iloczynie jest równa łącznej liczbie bitów po przecinku w mnożnej i mnożniku. Przykład. 3.7. Pomnożyć pisemnie liczby binarne A = 111.01 = 7.25 i B = 110.1 = 6.5. 11101 *1101 ------11101 00000 11101 +11101 ----------101111001 Uwzględniając trzy miejsca po przecinku uzyskuje się M = A * B = 111.01 * 110.1 = 101111.001 = 47.125. Sprawdzenie: 7.25 * 6.5 = 47.125. Przykład. 3.8. Pomnożyć pisemnie liczby binarne A = 111.1 = 7.5 i B = 111.1 = 7.5. 1111 *1111 ------23321 przeniesienie ---------1111 1111 1111 +1111 ---------11100001 Uwzględniając dwa miejsca po przecinku uzyskuje się M = A * B = 111.1 * 111.1 = 111000.01 = 56.25. Sprawdzenie: 7.5 * 7.5 = 56.25. 3.2.4. Dzielenie binarne Operacja dzielenia binarnego jest związana z odejmowaniem dzielnika od dzielnej. W przypadku dzielenia cyfr binarnych ai : bi wystarczy rozważyć tylko dzielenie przez jeden. Stąd, reguły dzielenia mają następującą postać: 1 0 Dzielna ai Dzielnik bi 1 1 --------------------------------Iloraz ei 1 0 Dzielenie można zakończyć w momencie, gdy pojawi się reszta lub kontynuować dzielenie, aż do uzyskania zadanej liczby miejsc po przecinku. Najlepiej przed dzieleniem przesunąć przecinek w dzielnej i dzielniku o taką samą ilość pozycji tak, aby w dzielniku nie występowały bity po przecinku. Przykład. 3.9. Podzielić pisemnie liczby binarne A = 11101.01 = 29.25 i B = 10.1 = 2.5. Przesunięcie przecinka A = 111010.1 oraz B = 101. 1011. ---------------111010.1 : 101 -101 ---------1001 -101 ---------1000 -101 ------------11.1 reszta Można kontynuować dzielenie i w rezultacie otrzymać część ułamkową. 1011.1011001100 ... ---------------111010.1 : 101 -101 ---------1001 -101 ---------1000 -101 ---------11 1 -10 1 ----------1 000 - 101 ----------0110 -101 ----------1000 -101 -------------... W wyniku dzielenia otrzymano iloraz E = A : B = 11101.01 : 10.1 = 1011 reszta 11.1/101 = 11 reszta 3.5/5. Sprawdzenie: 29.25 : 2.5 = 11.7 = 1011.10 (1100) ... . 3.3. Realizacja operacji arytmetycznych w systemach cyfrowych W systemach cyfrowych operacje arytmetyczne są wykonywane na liczbach o określonej liczbie bitów. W wyniku realizacji działań arytmetycznych pojawia się wynik, który jest zapamiętywany na określonej liczbie bitów. Na przykład w przypadku dodawania liczb n-bitowych często przyjmuje się, że wynik również zajmuje n bitów. Można zauważyć, że wykonanie określonej operacji arytmetycznej na liczbach o określonej liczbie bitów może dać wynik, który wykracza poza zakres wartości liczbowych reprezentowanych w danym kodzie na danej liczbie bitów. Wówczas powstaje nadmiar (ang. overflow), który musi być zasygnalizowany użytkownikowi układu cyfrowego. Powstawanie nadmiaru podczas dodawania liczb dodatnich w kodzie NKB ilustruje następujący przykład. Przykład. 3.10. Dodać dwie liczby 4-bitowe w kodzie NKB. Wynik sumowania zapamiętać na 4 bitach. Liczba A = 1100 = 12. Liczba B = 1010 = 10. 1100 +1010 -----C=1 0110 C - przeniesienie S = A + B = 1100 + 1010 = 10110 = 22. Sprawdzenie 12 + 10 = 22. W wyniku operacji sumowania pojawia się przeniesienie c=1 na pozycję numer cztery. Oznacza to, że zakres wyniku został przekroczony. Rozwiązaniem tego problemu jest wyposażenie układu cyfrowego w sygnalizację przeniesienia lub zwiększenie zakresu wyniku o jeden bit. W praktyce cyfrowe układy arytmetyczne wykonujące podstawowe działania są wyposażone w sygnał wyjściowy sygnalizujący nadmiar (np. jednostka arytmetyczno-logiczna procesora). Układy te sygnalizują także inne cechy wyniku jak: znak, wynik jest równy zero, wynik zawiera parzystą liczbę jedynek, itp. Bity te są nazywane w układach cyfrowych znacznikami (flagami, ang. flags). 3.3.1. Dodawanie liczb stałopozycyjnych Liczby dodatnie w kodach ZM, U1 i U2 są reprezentowane tak jak w kodzie NKB. Dodawanie takich liczb wykonuje się w sposób identyczny dla wszystkich kodów. W przypadku liczb A i B dodając bity z pozycji i-tej uwzględnia się również przeniesienie z pozycji mniej znaczącej. Dlatego w czasie sumowania na i-tej pozycji dodawane są trzy bity: dwa bity ai oraz bi należące do obu składników oraz przeniesienie ci z pozycji mniej znaczącej (i-1). Suma ai + bi + ci daje wynik si oraz przeniesienie wychodzące ci+1. Zasadę obliczania sumy si oraz przeniesienia ci+1 w przypadku sumatora jednobitowego pokazano poniżej. ai ci+1 bi ¦ ci si Łącząc szeregowo n sumatorów jednobitowych powstanie sumator n-bitowy. ai bi ci si ci+1 ---------------------------------------0 0 0 0 0 0 0 1 1 0 0 1 0 1 0 0 1 1 0 1 1 0 0 1 0 1 0 1 0 1 1 1 0 0 1 1 1 1 1 1 Sumowanie dwóch liczb o określonej liczbie bitów może dać wynik, który wykracza poza zakres wartości liczbowych reprezentowanych w danym kodzie na określonej liczbie bitów. Powstaje wówczas nadmiar, który musi być zasygnalizowany przez odpowiedni bit znacznikowy układu cyfrowego. Przykład. 3.11. Dodać dwie, dodatnie liczby 8-bitowe A=48 i B=58 w kodach NKB, ZM, U1, U2 oraz kodzie BCD. Wynik sumowania zapamiętać na 8 bitach. 48 +58 ----106 00110000 NKB,ZM,U1,U2 +00111010 ---------01101010 W przypadku kodu BCD otrzymuje się: 1 przeniesienie 0100 1000 +0101 1000 -----------1010 0000 = (10)(0) | nie jest cyfrą dziesiętną Otrzymany wynik nie jest prawidłowy. Na młodszej tetradzie pojawiło się 0 oraz przeniesienie na starszą tetradę. Natomiast na starszej tetradzie pojawiło się słowo nie należące do kodu BCD (liczba 10). W takich przypadkach proces sumowania rozszerza się o krok korekcyjny. Jeśli na i-tej tetradzie powstało przeniesienie lub wynik sumowania nie jest cyfrą dziesiętną, to do wyniku dodaje się 6 oraz ewentualne przeniesienie powstające na (i-1)-ej tetradzie. Dla rozpatrywanego przykładu 3.11 korekcja wyniku dla kodu BCD przebiega w sposób następujący: 1010 0000 = (10)(0) + 0110 0110 = (6)(6) ----------C=1 0000 0110 = (0)(6) W wyniku korekcji wyniku pojawiło się przeniesienie na trzecią tetradę. Otrzymana liczba ma więc w kodzie BCD następującą postać: 0001 0000 0110 = 106 Jest to poprawny wynik dodawania liczb A=48 i B=58. Przykład. 3.12. Dodać dwie, dodatnie liczby 8-bitowe A=78 i B=57 w kodach NKB, ZM, U1, U2 oraz kodzie BCD. Wynik sumowania zapamiętać na 8 bitach. 78 +57 ----135 1111 01001110 NKB,ZM,U1,U2 +00111001 ---------10000111 W kodzie NKB otrzymana suma jest równa 135, a więc wynik jest poprawny. Natomiast w kodach ZM, U1 i U2, ze względu na ustawiony bit znaku na najstarszej pozycji, otrzymany wynik jest ujemny. Rzeczywiście liczby 135 nie da się przedstawić na 7 bitach. Prawidłowe dodawanie takich liczb można wykonać jedynie na większej liczbie bitów. W rozpatrywanym przypadku wystarczy wykonać dodawanie na słowach 9-bitowych. 78 +57 ----135 1111 001001110 NKB,ZM,U1,U2 +000111001 ----------010000111 = 135 W przypadku kodu BCD otrzymuje się: 111 0111 1000 +0101 0111 -----------1100 1111 = (12)(15) W wyniku dodawania na obu tetradach pojawiły się słowa nie należące do kodu BCD (liczby 15 i 12). W celu otrzymania prawidłowego wyniku należy dokonać korekcji dodając do każdej tetrady 6. 1 11 1100 1111 = (12)(15) +0110 0110 = (6) (6) -----------0011 0101 = (3)(5) C=(1) (1) C=(1)– nadmiar (przeniesienie na trzecią tetradę) W wyniku dodawania otrzymano przeniesienie na trzecią tetradę. Otrzymana suma ma w kodzie BCD następującą postać: 0001 0011 0101 = 135 Jest to poprawny wynik dodawania liczb A=78 i B=57. 3.3.2. Odejmowanie liczb stałopozycyjnych Odejmowanie liczb w kodach uzupełnieniowych U1, U2 można sprowadzić do dodawania dwóch argumentów o przeciwnych znakach. W kodzie ZM odejmowanie dwóch liczb o przeciwnych znakach sprowadza się do porównania modułów liczb w celu ustalenia znaku wyniku jako znaku liczby o większym module. Następnie wyznacza się różnicę modułów przez odjęcie mniejszego modułu od większego modułu w sposób identyczny jak dla liczb w kodzie NKB. W przypadku odejmowania od ai = 0 wartości bi = 1 należy pobrać pożyczkę pi+1 = 1 wychodzącą z pozycji (i+1). Wartość tej pożyczki na pozycji (i) wynosi 2. Podczas odejmowania bitów na i-tej pozycji należy odjąć również pożyczkę pi wchodzącą z pozycji mniej znaczącej (i-1). Wzór na odejmowanie bitów z pozycji i-tej ma następującą postać: di = ai - bi - pi + 2∗pi+1 . Np. Odejmowanie A=2 i B=1. Różnica D=A-B=1. W tym przypadku p0=0, p1=1 i p2=0. W wyniku odejmowania d0 = a0 - b0 - p0 + 2∗p1 = 0 – 1 – 0 + 2∗1 = 1 oraz d1 = a1 – b1 – p1 + 2∗p2 = 1 – 0 – 1 + 2∗0 = 0. 2 10 - 01 ----01 (2) (1) (1) Poniżej przedstawiono sposób obliczania różnicy dwóch liczb di = ai - bi - pi + 2∗pi+1 z uwzględnieniem pożyczki. ai bi pi di pi+1 ---------------------------------------0 0 0 0 0 0 0 1 1 1 0 1 0 1 1 0 1 1 0 1 1 0 0 1 0 1 0 1 0 0 1 1 0 0 0 1 1 1 1 1 Przykład. 3.13. Odjąć w kodzie ZM dwie liczby 8-bitowe A=-28 i B=10. W kodzie ZM odejmowanie realizowane jest na modułach liczb a następnie uzupełniany jest znak wyniku. Porównanie modułów liczb prowadzi do przyjęcia ujemnego znaku wyniku. Odejmując od 28 liczbę 10 otrzymuje się: 00011100 = 28 - 00001010 = 10 -------------00010010 = 18 Uwzględniając znak wyniku otrzymana różnica w kodzie ZM ma wartość –18 = 10010010. Odejmowanie w kodzie ZM wymaga ustalenia znaku wyniku na podstawie porównania modułów argumentów. Wynika stąd, że w kodzie ZM odejmowanie realizuje się inaczej niż dodawanie w tym kodzie, które nie wymaga takiego porównywania. Jest to wada kodu ZM, która powoduje, że jest on rzadko stosowany. W przypadku kodów uzupełnieniowych U1 i U2 przedstawiona wada kodu ZM nie występuje. Odejmowanie wykonuje się w tych kodach w taki sam sposób jak dodawanie z uwzględnieniem zakresu liczb dodatnich i ujemnych w obu typach kodów. Odejmowanie w kodzie U1 wzoru: W kodzie U1 wartość dziesiętną liczby całkowitej R = an-1an-2...a1a0 można obliczyć ze n−2 R = −a n −1 (2 n −1 − 1) + ¦ a k 2 k . k =0 Dla liczb dodatnich (an-1=0). Dla liczb ujemnych (an-1=1), natomiast na pozostałych (n-1) bitach znajduje się liczba dodatnia X będąca dopełnieniem modułu liczby R do 2(n-1) –1 (suma |R| + X wynosi 2(n-1) -1). Dla R ujemnego wartość (n-1)-bitowej liczby X można obliczyć ze wzoru: n−2 X = ¦ a k 2 k = (2 n −1 − 1) + R . k =0 Sposób odejmowania zależy od wartości liczby X oraz znaków odejmowanych liczb. Przykład. 3.14. Przedstawić w 8-bitowym kodzie U1 liczbę R=-20. Podać wartość liczby X zdefiniowanej na pierwszych siedmiu bitach słowa kodowego. Obliczyć wartość W = |R| + X. -R = 20 = 0001 0100 X = 1101011 = 127 + (– 20) = 107 R = -20 = 1 1101011 W = |R| + X = 127. Odejmowanie liczb o różnych znakach Dodając do ujemnej liczby A (X = 2n-1-1 + A) dodatnią liczbę B (Y = B) obliczana jest suma bitów obu liczb z pozycji od 0 do n-2 (X + Y), która wynosi (2 n −1 − 1) + A + B . Jeśli moduł liczby ujemnej jest większy (równy) niż moduł liczby dodatniej, tj. |A| ≥ B, to suma A+B jest ujemna (równa zero) i wynik jest mniejszy (równy) od 2(n-1)-1. W tym przypadku nie następuje przeniesienie na pozycję (n-1) o wadze 2(n-1). Na najstarszej pozycji pozostaje bit znaku (an-1=1), a otrzymana liczba jest ujemna. Przedstawiony przypadek ilustruje następujący przykład. Przykład. 3.15. Dodać w 8-bitowym kodzie U1 liczby A=-20 i B=7. 1111 11101011 (-20) +00000111 (+7) ---------11110010 (-13) 00001101 (+13) W tym przypadku |A| > B. Nie powstało przeniesienie na pozycję najbardziej znaczącą (n-1) i wynik jest poprawny. W przypadku dodawania w kodzie U1 liczb n-bitowych A i B o przeciwnych znakach nieprawidłowy wynik pojawi się, gdy moduł liczby dodatniej jest większy od modułu liczby ujemnej, tj. gdy B > |A|. W tym przypadku na (n-1) bitach liczby ujemnej A, zapisanej w kodzie U1, zakodowana jest liczba dodatnia X będąca dopełnieniem modułu liczby do 2(n-1) -1, natomiast na odpowiednich (n-1) pozycjach liczby dodatniej B jest zakodowany jej moduł. Jeśli wartość modułu liczby B jest większa niż modułu A, to po dodaniu pierwszych (n-1) bitów pojawi się liczba większa od 2(n-1)–1. Spowoduje to pojawienie się przeniesienia na pozycję bitu znaku co prowadzi do zmiany bitu wyniku na 0 (wynik ma być dodatni). Wartość liczbowa wyniku jest równa sumie bitów obu liczb z pozycji od 0 do n-2, pomniejszonej o wartość przeniesienia na pozycję (n-1). Stąd, suma liczb ma wartość (2 n−1 − 1) + A + B − 2 n−1 = A + B − 1 . Jest to wartość nieprawidłowa. W takim przypadku należy wykonać krok korekcyjny i dodać do wyniku 1. Przedstawione rozważania ilustruje następujący przykład. Przykład. 3.16. Dodać w 8-bitowym kodzie U1 liczby A=-20 i B=45. 11 1111 11101011 (-20) +00101101 (+45) ---------C=1 00011000 (+24) W tym przypadku B >|A|. Powstało przeniesienie na pozycję bitu znaku. W wyniku dodawania otrzymano liczbę +24 oraz przeniesienie. Krok korekcyjny polega na dodaniu jedynki do wyniku: 00011000 (+24) + 00000001 (+1) korekcja ----------00011001 (+25) Konieczność dokonywania korekcji wyniku w przypadkach powstawania przeniesienia na najbardziej znaczącą pozycję jest wadą kodu U1, gdyż wydłuża czas dodawania. W skrajnym przypadku dodanie jedynki w ramach korekcji wyniku może spowodować, że przeniesienie będzie propagować przez wszystkie pozycje wyniku. Może to prowadzić do dwukrotnego zwiększenia czasu dodawania. Wady tej nie ma kod U2, w którym nie jest wymagana korekcja podczas dodawania liczb z przeciwnym znakiem. Odejmowanie liczb ujemnych Dodawanie liczb ujemnych A i B w kodzie U1 zawsze da przeniesienie wychodzące z pozycji (n-1), gdyż oba bity znaku są jedynkami. Jeśli suma bitów pochodzących z pozycji od 0 do (n-2) (X + Y)obu liczb jest większa lub równa 2(n-1)-1, to aby otrzymać prawidłowy wynik należy wykonać krok korekcyjny dodając do wyniku 1. Przykład. 3.17. Dodać w 8-bitowym kodzie U1 liczby A=-20 i B=-30. 1 1 11 1 1101011 +1 1100001 ---------C=1 1 1001100 0 0000001 ---------1 1001101 0 0110010 (-20)(107) (-30) (97) (-51) (+1) (-50) (50) korekcja Suma liczb (n-1)-bitowych jest większa niż 127 (107 + 97 = 204). W celu otrzymania prawidłowej wartości do wyniku dodano jeden. Przykład. 3.18. Dodać w 8-bitowym kodzie U1 liczby A=-85 i B=-42. 1 0101010 +1 1010101 ---------C=1 0 1111111 0 0000001 ---------1 0000000 (-85) (42) (-42) (85) (+127) (+1) korekcja (-127) Suma liczb (n-1)-bitowych jest równa 127 (42 + 85). W celu otrzymania prawidłowej wartości do wyniku dodano jeden. Jeśli suma bitów pochodzących z pozycji od 0 do (n-2) (X+Y) obu liczb jest mniejsza (n-1) niż 2 -1, to dodawanie liczb, nawet po uwzględnieniu korekcji, prowadzi do nieprawidłowego wyniku. Przykład. 3.19. Dodać w 8-bitowym kodzie U1 liczby A=-30 i B=-98. 1 1 1100001 +1 0011101 ---------C=1 0 1111110 0 0000001 ---------0 1111111 (-30) (97) (-98) (29) (+126) (+1) korekcja (+127) Suma liczb (n-1)-bitowych jest mniejsza niż 127 (97 + 29 = 126). Nawet po dodaniu jedynki nie otrzymano prawidłowego wyniku (A+B =–128). Jeśli jednak wykona się to samo dodawanie dla liczb 9-bitowych (n=9), to otrzyma się przypadek, w którym suma liczba (n-1) bitowych przekroczy 2(n-1)-1 = 255. Wówczas wynik będzie prawidłowy po dodaniu jedynki. 1 11100001 +1 10011101 ----------C=1 1 01111110 0 00000001 ----------1 01111111 (-30) (225) (-98) (157) (-129) (+1) korekcja (-128) Konieczność wykonywania kroku korekcyjnego w przypadku, gdy na pozycji najbardziej znaczącej (n-1) pojawia się przeniesienie, jest wadą kodu U1. Realizacja operacji odejmowania w kodzie U2 nie ma tej wady. Odejmowanie w kodzie U2 wzoru: W kodzie U2 wartość dziesiętną liczby całkowitej R = an-1an-2...a1a0 można obliczyć ze n−2 R = −a n −1 (2 n −1 ) + ¦ a k 2 k . k =0 Dodając do ujemnej liczby A dodatnią liczbę B obliczana jest suma bitów obu liczb z pozycji od 0 do n-2, która wynosi (2 n −1 ) + A + B . Jeśli suma ta przekroczy wartość 2(n-1) –1, to pojawi się przeniesienie na pozycję bitu znaku (pozycja o numerze n-1). Znak wyniku będzie wówczas równy 0 a wartość sumy wyniesie (2 n−1 ) + A + B − 2 n −1 = A + B . Wynika stąd, że dodawanie liczb z przeciwnym znakiem w kodzie U2 daje poprawny wynik bez kroku korekcyjnego. Przykład. 3.20. Dodać w 8-bitowym kodzie U2 liczby A=-20 i B=45. 11 11 11101100 (-20) +00101101 (+45) ---------C=1 00011001 (+25) Wynik dodawania jest poprawny i wynosi -20 + 45 = 25. Przykład. 3.21. Dodać w 8-bitowym kodzie U2 liczby A=20 i B=-45. 1 00010100 (+20) +11010011 (-45) ---------11100111 (-25) 00011001 (+25) Wynik dodawania jest poprawny i wynosi 20 - 45 = -25. Dodając dwie liczby ujemne można przekroczyć dopuszczalny zakres dla kodu U2 i wówczas na najbardziej znaczącej pozycji powstanie zero, co oznacza, że wynik jest dodatni. Nie jest to zgodne z prawdą, gdyż obie liczby są ujemne. W takim przypadku należy wykonać operacje na liczbach o większej liczbie bitów. Przykład. 3.22. Dodać w 8-bitowym kodzie U2 liczby A=-20 i B=-45. 1 11101100 (-20) +11010011 (-45) ---------C=1 10111111 (-65) Wynik dodawania jest poprawny i wynosi -20 -45 = -65. Przykład. 3.23. Dodać w 8-bitowym kodzie U2 liczby A=-40 i B=-120. 11 11011000 (-40) +10001000 (-120) --------C=1 01100000 (+96) W przypadku uwzględniania 8 bitów wynik nie jest prawidłowy. Jeśli uwzględni się liczby 9-bitowe, to otrzymany wynik będzie poprawny. 1 11 111011000 (-40) +110001000 (-120) ---------C=1 101100000 (-160) 010100000 (+160) 3.3.3. Mnożenie liczb stałopozycyjnych W systemie dwójkowym liczby A i B mnoży się w tylu krokach z ilu bitów składają się czynniki. Jeśli mnoży się pisemnie dwie liczby n-bitowe w kodzie NKB, to wykonuje się to w n krokach. W każdym kroku mnoży się jedną cyfrę mnożnika B przez mnożną A. W wyniku otrzymuje się iloczyn cząstkowy, który jest wpisywany z odpowiednim przesunięciem. Na końcu algorytmu sumowanych jest n iloczynów cząstkowych. Wynik mnożenia może być co najwyżej (n+n) – bitowy. Przykład. 3.24. Pomnożyć pisemnie w kodzie NKB 4-bitowe liczby binarne A = 0101 = 5 i B = 0111 = 7. Iloczyn A * B = 35. 0101 mnożna (+5) *0111 mnożnik (+7) ------2111 przeniesienie ---------0101 0101 0101 +0000 ---------0100011 iloczyn (+35) W urządzeniach cyfrowych stosuje się zwykle sumatory dwuargumentowe. Należy więc tak zmodyfikować algorytm mnożenia, aby już w każdym kroku wykonywać sumowanie iloczynów cząstkowych, a nie sumowanie wielu składników na końcu algorytmu. Dlatego w każdym kroku algorytmu mnożenia liczb w kodzie NKB wykonuje się dodawanie iloczynów cząstkowych i przesunięcie wyniku o jedną pozycję w prawo. Jednym ze składników dodawania jest zawsze iloczyn cząstkowy, a drugi składnik zależy od aktualnej wartości najmniej znaczącego bitu mnożnika (najbardziej skrajny prawy bit mnożnika). Jeśli jest on równy 1, to składnik jest mnożną, a jeśli jest on równy 0, to składnik jest zerem (słowem dwójkowym reprezentującym liczbę 0). W celu ilustracji działania algorytmu zostanie rozpatrzone mnożenie liczb +7 i +5. Oba czynniki można zapisać w kodzie NKB na czterech bitach. Iloczyny cząstkowe i wynik mnożenia mogą być co najwyżej 8-bitowe. Algorytm rozpoczyna się od zapisania mnożnika +5 na młodszych bitach 8-bitowego słowa (druk wytłuszczony), w którym będą składowane iloczyny cząstkowe. Na starszych bitach słowa jest wpisywane 0. Następnie wykonywane są cztery kroki złożone z dodawania i przesunięcia w prawo. Jeśli wartość bitu na najmniej znaczącej pozycji 8-bitowego słowa wynosi 0, to do czterech najbardziej znaczących bitów słowa jest dodawane 0, a jeśli wartość tego bitu wynosi 1, to do czterech najbardziej znaczących bitów słowa jest dodawana mnożna. Przykład. 3.25. Wykonać mnożenie czynników w kodzie NKB za pomocą algorytmu przeznaczonego dla układów cyfrowych. Pomnożyć 4-bitowe liczby binarne A = 0111 = +7 i B = 0101 = +5. Przyjąć wynik 8-bitowy. Iloczyn A * B = +35. Bity mnożnika zostały wytłuszczone. mnożna (+7) 0111 mnożnik (+5) 0101 ----------------------------------zapisanie argumentów 0000 0101 Krok 1. Dodanie mnożnej do starszej części 8-bitowego słowa i przesunięcie wyniku w prawo o jeden bit. 0000 0101 +0111 ----------0111 0101 Przesunięcie wyniku: 0011 1010 Krok 2. Dodanie zera do starszej części 8-bitowego słowa i przesunięcie wyniku w prawo o jeden bit. 0011 1010 +0000 ----------0011 1010 Przesunięcie wyniku: 0001 1101 Krok 3. Dodanie mnożnej do starszej części 8-bitowego słowa i przesunięcie wyniku w prawo o jeden bit. Przesunięcie wyniku: 0001 1101 +0111 ----------1000 1101 0100 0110 Krok 4. Dodanie zera do starszej części 8-bitowego słowa i przesunięcie wyniku w prawo o jeden bit. 0100 0110 +0000 ----------0100 0110 Przesunięcie wyniku: 0010 0011 = (+35) Drukiem wytłuszczonym zaznaczono kolejne bity mnożnika. Są one zastępowane bitami wyników cząstkowych, aż po czwartym kroku 8-bitowe słowo zawiera wynik. W przykładzie jest to słowo reprezentujące wartość +35. Algorytm mnożenia liczb w kodzie NKB Schemat blokowy algorytmu mnożenia START RH = 0 RL = mnożnik M = mnożna N = licznik T N R0 = 1 RH = RH + M RH = RH + 0 Przesunięcie R w prawo N=N-1 N T N=0 STOP Opis słowny algorytmu mnożenia 1. Na podstawie sumy liczby bitów mnożnej (A) i mnożnika (B) ustalić długość słowa wyniku R. 2. Na mniej znaczącej części słowa wyniku wpisać mnożnik, tj. RL = B. 3. Jeśli wartość najmniej znaczącego bitu wyniku wynosi 0, to do bardziej znaczącej części słowa wyniku dodać zero, tj. RH = RH + 0, w przeciwnym przypadku do bardziej znaczącej części słowa wyniku dodać mnożną, tj. RH = RH + A. 4. Przesunąć wynik cząstkowy o jedną pozycję w prawo (na najstarszą pozycję wchodzi 0 lub przeniesienie, jeśli powstało). 5. Jeśli wykonano liczbę kroków równą liczbie bitów mnożnika, to należy algorytm zakończyć, w przeciwnym wypadku należy przejść do wykonania kroku 3. W systemach cyfrowych czynniki oraz wyniki cząstkowe są przechowywane w rejestrach (np. w rejestrach procesora). Przedstawiony algorytm można zrealizować w układzie składającym się z dwóch rejestrów M i R oraz układu sumatora ALU (ang. arithmetic-logical unit). Na rysunku poniżej pokazano schemat układu. M ALU RH OV RL Sterowanie Rejestr R jest tzw. rejestrem przesuwającym, który umożliwia składowanie wyników cząstkowych oraz ich przesuwanie w prawo. Jest to rejestr o podwójnej długości słowa zawierającego czynnik. Składa się on z rejestru RH, zawierającego bardziej znaczącą połówkę rejestru R, oraz rejestru RL, zawierającego mniej znaczącą połówkę tego rejestru. Mnożna jest zapisywana do rejestru M. Układ sterowania jest odpowiedzialny za określenie liczby kroków algorytmu oraz kontrolę wartości najmniej znaczącego bitu rejestru RL. W każdym kroku dodawania wyników cząstkowych może pojawić się nadmiar. Jest on sygnalizowany za pomocą znacznika OV, którego stan jest analizowany przez układ sterowania. Jeśli w czasie mnożenia powstanie nadmiar, to system sterowania powinien podjąć odpowiednie kroki. Mogą one polegać na powiadomieniu operatora lub zwiększeniu długości słowa argumentów. Przedstawiony algorytm mnożenia liczb w kodzie NKB, po dokonaniu pewnych modyfikacji, może być również wykorzystywany do mnożenia liczb w kodzie ZM, U1 i U2. W przypadku mnożenia liczb ujemnych można określić znak wyniku, a następnie pomnożyć liczby dodatnie albo można stosować algorytmy specyficzne dla danych kodów. Przykład. 3.26. Wykonać mnożenie czynników w kodzie NKB za pomocą algorytmu przeznaczonego dla układów cyfrowych. Pomnożyć 4-bitowe liczby binarne A = 0111 = +7 i B = 0110 = +6. Przyjąć wynik 8-bitowy. Iloczyn A * B = +42. mnożna (+7) 0111 mnożnik (+6) 0110 ----------------------------------zapisanie argumentów 0000 0110 Krok 1. Dodanie zera do starszej części 8-bitowego słowa i przesunięcie wyniku w prawo o jeden bit. 0000 0110 +0000 ---------0000 0110 Przesunięcie wyniku: 0000 0011 Krok 2. Dodanie mnożnej do starszej części 8-bitowego słowa i przesunięcie wyniku w prawo o jeden bit. 0000 0011 +0111 ---------0111 0011 Przesunięcie wyniku: 0011 1001 Krok 3. Dodanie mnożnej do starszej części 8-bitowego słowa i przesunięcie wyniku w prawo o jeden bit. 0011 1001 +0111 ---------1010 1001 Przesunięcie wyniku: 0101 0100 Krok 4. Dodanie zera do starszej części 8-bitowego słowa i przesunięcie wyniku w prawo o jeden bit. 0101 0100 +0000 ---------0101 0100 Przesunięcie wyniku: 0010 1010 (+42). W przypadku, gdy dodawanie wyników cząstkowych daje przeniesienie należy zwiększyć długość słowa argumentów lub wprowadzić wartość przeniesienia na najstarszy bit. 3.3.4. Dzielenie liczb stałopozycyjnych W systemie dwójkowym dzielenie liczby A przez B można sprowadzić do odejmowania dzielnika B od dzielnej A. Operacja dzielenia pisemnego składa się z kilku kroków odejmowania. W wyniku dzielenia liczb dwójkowych w kodzie NKB otrzymuje się część całkowitą i resztę, którą można rozwinąć w ułamek z określoną dokładnością. Przykład. 3.27. Podzielić pisemnie w kodzie NKB liczbę binarną A = 01000010 = 66 i B = 1100 = 12. 101 (+5) --------01000010 : 1100 - 1100 ------------010010 - 1100 ------------00110 (+6) reszta Wynik działania A : B = 66 : 12 = 5 reszta 6, gdyż 66 = 5∗12 + 6. W układach cyfrowych dzielenie jest działaniem bardziej skomplikowanym niż mnożenie. Wynika to z faktu, że wynik może być ułamkiem, który musi być zapisany na skończonej liczbie bitów. Oznacza to, że może on być zapamiętany tylko z pewną dokładnością. W praktyce większość algorytmów dzielenia daje w wyniku część całkowitą z dzielenia (iloraz) i resztę. W algorytmie dzielenia liczb w kodzie NKB przyjmuje się, że dzielna A jest wpisywana do rejestru o podwójnej długości słowa, natomiast dzielnik B, wynik dzielenia i reszta są wpisywane do rejestrów o pojedynczej długości słowa. Algorytm zostanie przedstawiony na przykładzie dzielenia liczby 8-bitowej A = +42 przez liczbę 4-bitową B = +6. Na początku dzielna jest wpisywana do rejestru R o podwójnej długości słowa, a dzielnik do rejestru M o pojedynczej długości. Każdy krok algorytmu składa się z przesunięcia w lewo zawartości rejestru R oraz odjęcia od bardziej znaczącej części tego rejestru (RH) wartości dzielnika. Jeśli wynik odejmowania jest dodatni (brak bitu znaku w RH), to na najmniej znaczącą pozycję rejestru R wpisuje się jedynkę, a w rejestrze R pozostaje otrzymana różnica. Jeśli natomiast wynik odejmowania jest ujemny, to na najmniej znaczącą pozycję rejestru R wpisuje się zero, a bardziej znaczącą część tego rejestru przywraca się do postaci sprzed odejmowania. Liczba kroków algorytmu jest równa liczbie bitów słowa. Po wykonaniu ostatniego kroku w mniej znaczącej części rejestru R jest część całkowita z dzielenia (iloraz), a w bardziej znaczącej części jest reszta. Przykład. 3.28. Wykonać dzielenie w kodzie NKB za pomocą algorytmu przeznaczonego dla układów cyfrowych. Podzielić liczbę 8-bitową A = 0010 1010 = +42 przez liczbę 4-bitową B = 0110 = +6. Wynik obliczeń A : B = 42 : 6 = 7 reszta 0. Bity wyniku (ilorazu) zostały wytłuszczone. dzielna (+42) 0010 1010 dzielnik (+6) 0110 --------------------------------------Krok 1. Przesunięcie 8-bitowej dzielnej w lewo i odjęcie od jej starszej części 4-bitowego dzielnika. Przesunięcie: Odejmowanie: Przywrócenie: 0101 010_ -0110 ----------1111 0101 0100 wynik ujemny dopisanie 0 Krok 2. Przesunięcie dzielnej w lewo i odjęcie od jej starszej części dzielnika. Przesunięcie: Odejmowanie: Dzielna: 1010 100_ -0110 ----------0100 0100 1001 wynik dodatni dopisanie 1 Krok 3. Przesunięcie dzielnej w lewo i odjęcie od jej starszej części dzielnika. Przesunięcie: Odejmowanie: Dzielna: 1001 001_ -0110 ----------0011 0011 0011 wynik dodatni dopisanie 1 Krok 4. Przesunięcie dzielnej w lewo i odjęcie od jej starszej części dzielnika. Przesunięcie: Odejmowanie: Dzielna: 0110 011_ -0110 ----------0000 0000 0111 wynik dodatni dopisanie 1 Drukiem wytłuszczonym zaznaczono kolejne bity wyniku. W starszej części rejestru zawierającego dzielną jest słowo reprezentujące resztę (wartość +0), a w młodszej części wartość reprezentująca wynik (wartość +7). Algorytm dzielenia liczb w kodzie NKB Schemat blokowy algorytmu dzielenia START R = (RH, RL) = dzielna M = dzielnik N = licznik Przesunięcie R w lewo RH = RH - M N T Czy RH ujemne? R0 = 1 R0 = 0 RH = RH + M N=N-1 N N=0 T STOP Opis słowny algorytmu dzielenia 1. Wpisać dzielną (A) do rejestru R o podwójnej długości słowa oraz dzielnik (B) do rejestru M o pojedynczej długości słowa. Wpisać do licznika kroków długość słowa. 2. Przesunąć zawartość rejestru R o jedną pozycję w lewo. W rejestrze R wartość najmniej znaczącego bitu R0 pozostawić nieokreśloną. 3. Obliczyć różnicę RH = RH - M. 4. Jeśli wartość rejestru RH jest ujemna (najstarszy bit równy 1), to podstawić R0 = 0 i przywrócić wartość RH sprzed odejmowania, tj. RH = RH + M. 5. Jeśli wartość rejestru RH jest dodatnia (najstarszy bit równy 0), to podstawić R0 = 1 i pozostawić zawartość rejestru R bez zmian. 6. Jeśli wykonano zadaną liczbę kroków, to zakończyć algorytm, w przeciwnym wypadku należy przejść do wykonania kroku 2. Przykład. 3.29. Wykonać dzielenie w kodzie NKB za pomocą algorytmu przeznaczonego dla układów cyfrowych. Podzielić liczbę 10-bitową A = 00010 00010 = +70 przez liczbę 5-bitową B = 01100 = +12. Wynik obliczeń A : B = 70 : 12 = 5 reszta 10. Bity wyniku (ilorazu) zostały wytłuszczone. dzielna (+70) 00010 00110 dzielnik (+12) 01100 ----------------------------------------Krok 1. Przesunięcie 10-bitowej dzielnej w lewo i odjęcie od jej starszej części 5-bitowego dzielnika. Przesunięcie: Odejmowanie: Przywrócenie: 00100 0110_ -01100 ----------11000 00100 01100 wynik ujemny dopisanie 0 Krok 2. Przesunięcie dzielnej w lewo i odjęcie od jej starszej części dzielnika. Przesunięcie: Odejmowanie: Przywrócenie: 01000 1100_ -01100 ----------11100 01000 11000 wynik ujemny dopisanie 0 Krok 3. Przesunięcie dzielnej w lewo i odjęcie od jej starszej części dzielnika. Przesunięcie: Odejmowanie: Dzielna: 10001 1000_ -01100 ----------00101 wynik dodatni 00101 10001 dopisanie 1 Krok 4. Przesunięcie dzielnej w lewo i odjęcie od jej starszej części dzielnika. Przesunięcie: Odejmowanie: Przywrócenie: 01011 0001_ -01100 ----------11111 01011 00010 wynik ujemny dopisanie 0 Krok 5. Przesunięcie dzielnej w lewo i odjęcie od jej starszej części dzielnika. Przesunięcie: Odejmowanie: Dzielna: 10110 0010_ -01100 ----------01010 wynik dodatni 01010 00101 dopisanie 1 W starszej części rejestru zawierającego dzielną jest słowo reprezentujące resztę (wartość +10), a w młodszej części wartość reprezentująca wynik (wartość +5). Wynik jest poprawny. Przedstawiony algorytm dzielenia liczb w kodzie NKB, po dokonaniu pewnych modyfikacji, może być również wykorzystywany do dzielenia liczb w kodzie ZM, U1 i U2. W przypadku dzielenia liczb ujemnych można określić znak wyniku, a następnie podzielić liczby dodatnie albo można stosować algorytmy specyficzne dla danych kodów.