I metoda konwersji bin → hex

Zanim napiszemy program konwertujący liczbę dwójkową do systemu o podstawie 16 (szesnastkowego), omówimy niezbędne do wykonania czynności. Całą operację przeprowadzimy dwuetapowo: najpierw liczbę dwójkową przedstawimy w systemie dziesiętnym. Następnie zamienimy ją na odpowiednik w systemie szesnastkowym.

Metodę konwersji pokażemy na przykładzie. Ułatwi nam to zrozumienie komputerowej realizacji algorytmu.

Ważne!

Pamiętaj, że w systemie o podstawie 16 oprócz cyfr od 0 do 9 wykorzystywane są symbole literowe z zakresu od A do F. Oto odpowiadające im wartości dziesiętne:

Symbol

Wartość

A

10

B

11

C

12

D

13

E

14

F

15

Przykład 1

Zapiszemy liczbę 10100111Indeks dolny (2) w postaci szesnastkowej.

101001112=127+125+
+122+121+120=16710

Najpierw mnożymy wszystkie cyfry liczby dwójkowej przez odpowiadające im wagi, czyli potęgi liczby 2. Po zsumowaniu iloczynów otrzymujemy zapis liczby w postaci dziesiętnej.

Oto wynik pierwszej konwersji:

101001112=16710

Następnie przedstawimy liczbę dziesiętną w postaci szesnastkowej.

REZwxvRwiORp5
Źródło: Contentplus.pl Sp. z o.o., licencja: CC BY-SA 3.0.

W tym celu wykonujemy następujące czynności:

  1. Dzielimy liczbę przez 16 (czyli przez podstawę systemu szesnastkowego).

  2. Zapamiętujemy iloraz oraz resztę z dzielenia.

  3. Wracamy do punktu 1. Dzielimy przez 16 obliczony wcześniej iloraz. Czynności opisane w punktach 1. i 2. wykonujemy dopóty, dopóki iloraz jest większy niż zero.

  4. Rezultatem konwersji są reszty z dzielenia, zapisane w kolejności od ostatniej do pierwszej.

Po zakończeniu całej operacji otrzymujemy wynik:

101001112=16710=A716

Realizacja algorytmu w języku C++

Możemy już przejść do napisania programu, który zamieni liczbę w systemie dwójkowym na system szesnastkowy.

Zaczniemy od napisania funkcji odpowiadającej za konwersję liczby binarnej do systemu dziesiętnego. Nazwiemy ją konwertujBinDec(). Jako parametrparametr funkcjiparametr funkcja przyjmie liczbę zapisaną w systemie dwójkowym. Zwróć uwagę, że podajemy ją w postaci ciągu znaków liczbaBin (jest to istotne, ponieważ jej elementy są traktowane jak znaki kodu ASCII):

Linia 1. int konwertujBinDec otwórz nawias okrągły std dwukropek dwukropek string liczbaBin zamknij nawias okrągły otwórz nawias klamrowy. Linia 2. int liczbaDec znak równości 0 średnik. Linia 3. int bit znak równości 0 średnik. Linia 4. int waga znak równości 1 średnik prawy ukośnik prawy ukośnik ponieważ 2 kareta 0 znak równości 1. Linia 6. for otwórz nawias okrągły int i znak równości liczbaBin kropka length otwórz nawias okrągły zamknij nawias okrągły minus 1 średnik i zamknij nawias ostrokątny znak równości 0 średnik i minus minus zamknij nawias okrągły otwórz nawias klamrowy. Linia 7. bit znak równości liczbaBin otwórz nawias kwadratowy i zamknij nawias kwadratowy minus apostrof 0 apostrof średnik. Linia 8. liczbaDec znak równości liczbaDec plus bit asterysk waga średnik. Linia 9. waga asterysk znak równości 2 średnik. Linia 10. zamknij nawias klamrowy. Linia 12. return liczbaDec średnik. Linia 13. zamknij nawias klamrowy.

Omówmy poszczególne linie kodu.

Na początku deklarujemy trzy zmienne typu całkowitego i nadajemy im wartości początkowe. Będą to:

  • bit = 0, którą wykorzystamy do przechowywania wartość aktualnie rozpatrywanego bitu

  • liczbaDec = 0, która będzie przechowywała nasz rezultat konwersji

  • waga = 1, która będzie przechowywała wagę obecnie rozpatrywanego bitu

Następnie tworzymy pętlę for, w której będziemy kolejno przechodzili po znakach naszej liczby binarnej od końca, tj. zaczynając od bitu o najmniejszej wadze. W każdym cyklu pętli for wykonamy następujące operacje:

  • Zmiennej bit przypisujemy wartość liczbaBin[i] - '0'. Innymi słowy, nadajemy jej wartość kodu ASCII znaku zapisanego w tablicy liczbaBin[], pomniejszoną o kod ASCII znaku '0'. W rezultacie bit przybiera wartość 0 lub 1. Wynika to z faktu, że zmienna liczbaBin[i] jest znakiem '0' lub '1'; odpowiadające im wartości w kodzie ASCII wynoszą – kolejno – 48 i 49. Kiedy liczbaBin[i] będzie znakiem '1', zostanie wykonane działanie 49‑48, a bit przyjmie wartość 1. Jeżeli liczbaBin[i] to znak '0', po operacji odejmowania (48‑48) bit wyniesie 0.W każdym cyklu pętli for mnożymy ją przez podstawę systemu binarnego, czyli 2.

  • Do zmiennej liczbaDec przypisujemy wartość liczbaDec + bit*waga, czyli obliczony do tej pory wynik powiększymy o waga jeżeli bit będzie równy 1 – w przeciwnym razie wartość liczbaDec pozostanie bez zmian.

  • Zmienną waga pomnożymy przez podstawę systemu liczbowego, czyli 2

Na koniec zwracamy wynik konwersji, czyli liczbę zapisaną w systemie dziesiętnym. Korzystamy z instrukcji return liczbaDec.

Już wiesz

W każdym cyklu pętli for podwajamy wartość zmiennej waga za pomocą operatora przypisania *=.

Ten sam efekt uzyskalibyśmy, wydając polecenie:

Linia 1. waga znak równości waga asterysk 2 średnik.
Ważne!

Ponieważ korzystamy z funkcji std::to_string(), musimy dołączyć do programu odpowiednią bibliotekę:

Linia 1. kratka include otwórz nawias ostrokątny string zamknij nawias ostrokątny.

Pierwsza funkcja jest zatem gotowa. Pora zamienić liczbę dziesiętną na szesnastkową.

Posłużymy się funkcją o nazwie konwertujDecHex(). Jej jedynym parametrem będzie liczba dziesiętna, otrzymana w wyniku działania funkcji konwertujBinDec():

Linia 1. std dwukropek dwukropek string konwertujDecHex otwórz nawias okrągły int liczbaDec zamknij nawias okrągły otwórz nawias klamrowy. Linia 2. if otwórz nawias okrągły liczbaDec znak równości znak równości 0 zamknij nawias okrągły otwórz nawias klamrowy. Linia 3. return cudzysłów 0 cudzysłów średnik. Linia 4. zamknij nawias klamrowy. Linia 6. std dwukropek dwukropek string liczbaHex znak równości cudzysłów cudzysłów średnik. Linia 7. int reszta średnik. Linia 9. while otwórz nawias okrągły liczbaDec zamknij nawias ostrokątny 0 zamknij nawias okrągły otwórz nawias klamrowy. Linia 10. if otwórz nawias okrągły liczbaDec procent 16 zamknij nawias ostrokątny znak równości 0 ampersant ampersant liczbaDec procent 16 otwórz nawias ostrokątny znak równości 9 zamknij nawias okrągły otwórz nawias klamrowy. Linia 11. reszta znak równości liczbaDec procent 16 średnik. Linia 12. liczbaHex znak równości std dwukropek dwukropek to podkreślnik string otwórz nawias okrągły reszta zamknij nawias okrągły plus liczbaHex średnik. Linia 13. zamknij nawias klamrowy else otwórz nawias klamrowy. Linia 14. reszta znak równości liczbaDec procent 16 minus 10 plus apostrof A apostrof średnik. Linia 15. char znak znak równości reszta średnik. Linia 16. liczbaHex znak równości znak plus liczbaHex średnik. Linia 17. zamknij nawias klamrowy. Linia 19. liczbaDec znak równości liczbaDec prawy ukośnik 16 średnik. Linia 20. zamknij nawias klamrowy. Linia 22. return liczbaHex średnik. Linia 23. zamknij nawias klamrowy.

Na samym początku należy sprawdzić, czy podany do funkcji argumentargument funkcjiargument jest zerem. Jeżeli tak, funkcja od razu powinna zwrócić ciąg znaków „0”.

Kolejnym krokiem jest deklaracja zmiennych:

  • std::string liczbaHex – jest to tablica znaków, w której zapiszemy wynik konwersji.

  • int reszta – będziemy w niej przechowywać reszty z dzielenia przez 16.

Następnie otwieramy pętlę while. Dzięki zapisanym w niej instrukcjom sprawdzimy, czy reszta z dzielenia konwertowanej liczby mieści się  w przedziale <0, 9>.

  • Jeżeli tak jest, przypisujemy zmiennej reszta wynik operacji liczbaDec % 16. Następnie, korzystając z funkcji std::to_string(), zamieniamy wartość całkowitą na znakową i dopisujemy („doklejamy”) ją do zmiennej liczbaHex.

  • Jeżeli reszta z dzielenia jest większa niż 9, w zmiennej reszta zapisujemy wynik operacji liczbaDec % 16 - 10 + 'A'. Odjęcie liczby 10, a następnie dodanie wartości odpowiadającej w tablicy ASCII literze 'A' spowoduje, że zmienna reszta przybierze wartości odpowiadające pozycjom znaków od 'A' do 'F' w tablicy ASCII. Przykładowo, jeżeli wynik działania liczbaDec % 16 będzie równy 14 (w notacji szesnastkowej odpowiada mu znak 'E'), to zostanie wykonana instrukcja reszta = 14 - 10 + 65. Jej wynikiem jest 69, czyli liczbowy odpowiednik znaku 'E' w tablicy ASCII. Przypisując zmiennej znak wartość 69 otrzymujemy literę 'E'. Następnie dopisujemy ją do zmiennej liczbaHex.

Musimy pamiętać, aby w każdym cyklu pętli podzielić iloraz liczbaDec przez podstawę systemu szesnastkowego. W innym przypadku pętla będzie działać w nieskończoność:

Linia 1. liczbaDec znak równości liczbaDec prawy ukośnik 16 średnik.

Na końcu zwracamy wynik konwersji, czyli zmienną liczbaHex.

Niezbędne funkcje mamy już napisane.

Dodajmy jeszcze instrukcje, dzięki którym użytkownik poda liczbę do przekształcenia. Odpowiedni kod umieszczamy w funkcji głównej int main():

Linia 1. std dwukropek dwukropek string liczbaTest średnik. Linia 3. std dwukropek dwukropek cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Podaj liczbę w systemie binarnym przecinek która ma zostać przekonwertowana do systemu szesnastkowego cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny std dwukropek dwukropek endl średnik. Linia 4. std dwukropek dwukropek cin zamknij nawias ostrokątny zamknij nawias ostrokątny liczbaTest średnik.

Ostatnim etapem jest wywołanie funkcji dla liczby podanej jako argument. Zwróć uwagę, że musimy zdefiniować zmienną liczbaDec, w której zapiszemy wynik pierwszego etapu konwersji (bin → dec). Wynika to z faktu, że zastosowany algorytm nie dokonuje bezpośredniej konwersji między systemami bin → hex.

Linia 1. int liczbaDec znak równości konwertujBinDec otwórz nawias okrągły liczbaTest zamknij nawias okrągły średnik. Linia 3. std dwukropek dwukropek cout otwórz nawias ostrokątny otwórz nawias ostrokątny konwertujDecHex otwórz nawias okrągły liczbaDec zamknij nawias okrągły średnik.

Oto cały kod programu:

Linia 1. kratka include otwórz nawias ostrokątny iostream zamknij nawias ostrokątny. Linia 2. kratka include otwórz nawias ostrokątny string zamknij nawias ostrokątny. Linia 4. int konwertujBinDec otwórz nawias okrągły std dwukropek dwukropek string liczbaBin zamknij nawias okrągły otwórz nawias klamrowy. Linia 5. int liczbaDec znak równości 0 średnik. Linia 6. int bit znak równości 0 średnik. Linia 7. int waga znak równości 1 średnik prawy ukośnik prawy ukośnik dlatego że 2 kareta 0 znak równości 1. Linia 9. for otwórz nawias okrągły int i znak równości liczbaBin kropka length otwórz nawias okrągły zamknij nawias okrągły minus 1 średnik i zamknij nawias ostrokątny znak równości 0 średnik i minus minus zamknij nawias okrągły otwórz nawias klamrowy. Linia 10. bit znak równości liczbaBin otwórz nawias kwadratowy i zamknij nawias kwadratowy minus apostrof 0 apostrof średnik. Linia 11. liczbaDec znak równości liczbaDec plus bit asterysk waga średnik. Linia 12. waga asterysk znak równości 2 średnik. Linia 13. zamknij nawias klamrowy. Linia 15. return liczbaDec średnik. Linia 16. zamknij nawias klamrowy. Linia 18. std dwukropek dwukropek string konwertujDecHex otwórz nawias okrągły int liczbaDec zamknij nawias okrągły otwórz nawias klamrowy. Linia 19. if otwórz nawias okrągły liczbaDec znak równości znak równości 0 zamknij nawias okrągły otwórz nawias klamrowy. Linia 20. return cudzysłów 0 cudzysłów średnik. Linia 21. zamknij nawias klamrowy. Linia 23. std dwukropek dwukropek string liczbaHex znak równości cudzysłów cudzysłów średnik. Linia 24. int reszta średnik. Linia 26. while otwórz nawias okrągły liczbaDec zamknij nawias ostrokątny 0 zamknij nawias okrągły otwórz nawias klamrowy. Linia 27. if otwórz nawias okrągły liczbaDec procent 16 zamknij nawias ostrokątny znak równości 0 ampersant ampersant liczbaDec procent 16 otwórz nawias ostrokątny znak równości 9 zamknij nawias okrągły otwórz nawias klamrowy. Linia 28. reszta znak równości liczbaDec procent 16 średnik. Linia 29. liczbaHex znak równości std dwukropek dwukropek to podkreślnik string otwórz nawias okrągły reszta zamknij nawias okrągły plus liczbaHex średnik. Linia 30. zamknij nawias klamrowy else otwórz nawias klamrowy. Linia 31. reszta znak równości liczbaDec procent 16 minus 10 plus apostrof A apostrof średnik. Linia 32. char znak znak równości reszta średnik. Linia 33. liczbaHex znak równości znak plus liczbaHex średnik. Linia 34. zamknij nawias klamrowy. Linia 36. liczbaDec znak równości liczbaDec prawy ukośnik 16 średnik. Linia 37. zamknij nawias klamrowy. Linia 39. return liczbaHex średnik. Linia 40. zamknij nawias klamrowy. Linia 42. int main otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 43. std dwukropek dwukropek string liczbaTest średnik. Linia 45. std dwukropek dwukropek cout otwórz nawias ostrokątny otwórz nawias ostrokątny cudzysłów Podaj liczbę w systemie binarnym przecinek która ma zostać przekonwertowana do systemu szesnastkowego cudzysłów otwórz nawias ostrokątny otwórz nawias ostrokątny std dwukropek dwukropek endl średnik. Linia 46. std dwukropek dwukropek cin zamknij nawias ostrokątny zamknij nawias ostrokątny liczbaTest średnik. Linia 48. int liczbaDec znak równości konwertujBinDec otwórz nawias okrągły liczbaTest zamknij nawias okrągły średnik. Linia 50. std dwukropek dwukropek cout otwórz nawias ostrokątny otwórz nawias ostrokątny konwertujDecHex otwórz nawias okrągły liczbaDec zamknij nawias okrągły średnik. Linia 52. return 0 średnik. Linia 53. zamknij nawias klamrowy.

II metoda konwersji bin → hex

Przekształcenia liczby dwójkowej w szesnastkową możemy dokonać także wykorzystując fakt, że po podniesieniu liczby 2 (czyli podstawy systemu binarnego) do czwartej potęgi uzyskamy liczbę 16 (czyli podstawę systemu szesnastkowego).

24=16

Każdy znak systemu szesnastkowego da się więc zapisać za pomocą czterech bitów.

Przeanalizujmy metodę konwersji:

Przykład 2

Chcemy zapisać liczbę 110101012 w postaci szesnastkowej. Wykorzystamy fakt, że oba systemy mają bazy skojarzonebazy skojarzonebazy skojarzone.

01012=516
11012=D16

A zatem otrzymujemy wynik:

110101012=D516

Konwersja części ułamkowej

Korzystając z właściwości baz skojarzonych możemy także konwertować część ułamkową liczby. Oto przykład:

Przykład 3

Zapiszemy liczbę 0,1010110101112 w systemie szesnastkowym.

Ry8SOmqJgWgio
Konwersja liczby z systemu binarnego na system szesnastkowy
Źródło: Contentplus.pl sp. z o.o., licencja: CC BY-SA 3.0.

W kolejnej sekcji zaimplementujemy ten właśnie algorytm.

Słownik

bazy skojarzone
bazy skojarzone

bazy systemów liczbowych, w przypadku których podstawa jednego systemu jest potęgą bazy systemu drugiego

parametr funkcji
parametr funkcji

element składni w określonym języku programowania; umożliwia komunikację pomiędzy podprogramem (funkcją) wywołanym a programem wywołującym; parametry określa się w nagłówku podprogramu (przy jego definicji)

argument funkcji
argument funkcji

element składni w określonym języku programowania, który w wyniku wywołania podprogramu zostaje utożsamiony (skojarzony) z określonym parametrem podprogramu