Wróć do informacji o e-podręczniku Wydrukuj Pobierz materiał do PDF Pobierz materiał do EPUB Pobierz materiał do MOBI Zaloguj się, aby dodać do ulubionych Zaloguj się, aby skopiować i edytować materiał Zaloguj się, aby udostępnić materiał Zaloguj się, aby dodać całą stronę do teczki

Zanim przystąpimy do implementacji algorytmu konwersji liczb z systemu dwójkowego na dziesiętny, przypomnijmy, w jaki sposób dokonywane jest takie przekształcenie. Przeanalizujmy przykład zamiany liczby zapisanej w systemie dwójkowym (binarnym) na system dziesiętny, czyli o podstawie 10. Ułatwi to późniejsze zaimplementowanie algorytmu w języku C++.

Dokonamy konwersji liczby 1011 z systemu dwójkowego na dziesiętny.

1011(2)()(10)

Jak rozwiązalibyśmy to zadanie, gdybyśmy mieli do dyspozycji kartkę i długopis?

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

Konwersja polega na mnożeniu kolejnych bitów (zaczynając od najmłodszego bitunajmłodszy bitnajmłodszego bitu i kończąc na najstarszym bicienajstarszy bitnajstarszym bicie) przez wagę pozycji, czyli kolejne potęgi liczby 2 (zaczynając od potęgi zerowej). Po zsumowaniu iloczynów częściowych otrzymamy wynik – liczbę zapisaną w systemie dziesiętnym.

Oto wynik końcowy wraz z odpowiednim zapisem:

1011(2)11(10)

Komputerowa realizacja w języku C++

Teraz zastanówmy się, jak zaimplementować omówiony algorytm przy użyciu języka programowania C++.

Algorytm zamiany liczby z systemu binarnego na system dziesiętny zapiszemy w ciele funkcji o nazwie konwertujBinDec(). Zwróci ona zmienną typu całkowitego (int) – będzie to liczba przekształcona do postaci dziesiętnej. Jako argument funkcja przyjmie liczbę zapisaną w systemie binarnym i przechowywaną w zmiennej typu string liczbaBin. Dlaczego użyjemy zmiennej typu string? W tym przypadku łatwiej będzie użyć właśnie tego typu zmiennej – podczas konwersji potrzebna jest znajomość wartości liczbowych poszczególnych cyfr, nie zaś całej liczby.

Ważne!

W przypadku operowania na zmiennych typu string pamiętajmy o użyciu odpowiedniej biblioteki:

Linia 1. kratka include otwórz nawias ostrokątny string zamknij nawias ostrokątny.
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 3. using namespace std średnik. Linia 5. int konwertujBinDec otwórz nawias okrągły string liczbaBin zamknij nawias okrągły otwórz nawias klamrowy. Linia 7. zamknij nawias klamrowy.

Następnie zadeklarujmy kilka zmiennych:

  • int wynik – zmienna, w której będziemy sumować kolejne iloczyny częściowe powstałe wskutek mnożenia wag przez bity. Będzie to wartość zwracana przez funkcję konwertujBinDec(),

  • int waga – będzie przyjmować kolejne wagi bitów, czyli kolejne potęgi liczby 2,

  • int bit – do niej zapiszemy konkretny bit konwertowanej liczby.

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 3. using namespace std. Linia 5. int konwertujBinDec otwórz nawias okrągły string liczba podkreślnik bin zamknij nawias okrągły otwórz nawias klamrowy. Linia 6. int wynik znak równości 0 średnik. Linia 7. int waga znak równości 1 średnik. Linia 8. int bit znak równości 0 średnik. Linia 9. zamknij nawias klamrowy.

Zmienna waga na początku przyjmuje wartość 1, ponieważ wagą najmłodszego bitu jest 2Indeks górny 0, czyli 1.

Napiszmy teraz pętlę typu for, w której kolejne bity, zaczynając od najmłodszego, będą mnożone przez odpowiadające im wagi.

Linia 1. int konwertujBinDec otwórz nawias okrągły string liczbaBin zamknij nawias okrągły otwórz nawias klamrowy. Linia 2. int wynik znak równości 0 średnik. Linia 3. int waga znak równości 1 średnik. Linia 4. int bit znak równości 0 średnik. 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. wynik znak równości wynik plus bit asterysk waga średnik. Linia 9. waga znak równości waga asterysk 2 średnik. Linia 10. zamknij nawias klamrowy. Linia 12. return wynik średnik. Linia 13. zamknij nawias klamrowy.

Omówmy teraz poszczególne fragmenty kodu.

  • int bit = liczbaBin[i] - '0' → w zmiennej typu int zapisujemy zmienną typu string i odejmujemy od niej liczbę odpowiadającą w kodzie ASCII znakowi zera. Dzięki temu w zmiennej bit zostaje zapisana liczba 0 lub 1. Zmienna liczbaBin[i] w kodzie ASCII to znak '0' lub '1' (ponieważ tylko takie liczby mogą pojawić się w systemie binarnym), a odpowiadające tym znakom liczby to, kolejno, 48 i 49. Oznacza to, że jeżeli liczbaBin[i] będzie znakiem '1', zostanie wykonane działanie 49–48, czyli zmienna bin przyjmie wartość liczbową 1. Jeżeli natomiast liczbaBin[i] będzie znakiem '0', wykonane zostanie działanie 48–48, a zmienna bin przyjmie wartość liczbową 0,

  • wynik = wynik + bit * waga → dodajemy kolejne iloczyny częściowe,

  • waga = waga * 2 → aby uzyskać wagę kolejnej pozycji, mnożymy aktualną wagę razy podstawę systemu, czyli 2.

Napiszmy kod, który umożliwi użytkownikowi wpisanie własnej liczby w celu wykonania konwersji do systemu dziesiętnego. Skorzystamy ze strumienia cin. Przeanalizujmy poniższy fragment kodu:

Linia 1. string liczbaTest średnik. Linia 3. cin zamknij nawias ostrokątny zamknij nawias ostrokątny liczbaTest średnik.

Oczywiście musimy zadeklarować zmienną liczbaTest, do której zapisana zostanie informacja podana przez użytkownika.

Kolejnym krokiem będzie wywołanie funkcji konwertujBinDec() dla argumentu liczbaTest i wypisanie wyniku (czyli liczby przekształconej do postaci dziesiętnej). W tym przypadku posłużymy się strumieniem cout.

Oto kod całego 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 3. kratka include otwórz nawias ostrokątny cstdlib zamknij nawias ostrokątny. Linia 4. using namespace std średnik. Linia 6. int konwertujBinDec otwórz nawias okrągły string liczbaBin zamknij nawias okrągły otwórz nawias klamrowy. Linia 7. int wynik znak równości 0 średnik. Linia 8. int waga znak równości 1 średnik. Linia 9. int bit znak równości 0 średnik. Linia 11. 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 12. bit znak równości liczbaBin otwórz nawias kwadratowy i zamknij nawias kwadratowy minus apostrof 0 apostrof średnik. Linia 13. wynik znak równości wynik plus bit asterysk waga średnik. Linia 14. waga znak równości waga asterysk 2 średnik. Linia 15. zamknij nawias klamrowy. Linia 17. return wynik średnik. Linia 18. zamknij nawias klamrowy. Linia 20. int main otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 21. string liczbaTest średnik. Linia 23. cin zamknij nawias ostrokątny zamknij nawias ostrokątny liczbaTest średnik. Linia 24. cout otwórz nawias ostrokątny otwórz nawias ostrokątny konwertujBinDec otwórz nawias okrągły liczbaTest zamknij nawias okrągły średnik. Linia 26. return 0 średnik. Linia 27. zamknij nawias klamrowy.

Alternatywnym rozwiązaniem powyższego problemu jest zastosowanie schematu Hornera przy konwersji. Pozwoli to zmniejszyć złożoność obliczeniową algorytmu do złożoności liniowej.

Poniższej przedstawiona została implementacja rozwiązania alternatywnego:

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 3. kratka include otwórz nawias ostrokątny cstdlib zamknij nawias ostrokątny. Linia 4. using namespace std średnik. Linia 6. int konwertujBinDec otwórz nawias okrągły string liczbaBin zamknij nawias okrągły otwórz nawias klamrowy. Linia 7. int wynik znak równości 0 średnik. Linia 8. int bit znak równości 0 średnik. Linia 10. for otwórz nawias okrągły int i znak równości 0 średnik i otwórz nawias ostrokątny liczbaBin kropka size otwórz nawias okrągły zamknij nawias okrągły średnik i plus plus zamknij nawias okrągły otwórz nawias klamrowy. Linia 11. bit znak równości liczbaBin otwórz nawias kwadratowy i zamknij nawias kwadratowy minus apostrof 0 apostrof średnik. Linia 12. wynik znak równości wynik asterysk 2 plus bit średnik. Linia 13. zamknij nawias klamrowy. Linia 15. return wynik średnik. Linia 16. zamknij nawias klamrowy. Linia 18. int main otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 19. string liczbaTest średnik. Linia 21. cin zamknij nawias ostrokątny zamknij nawias ostrokątny liczbaTest średnik. Linia 22. cout otwórz nawias ostrokątny otwórz nawias ostrokątny konwertujBinDec otwórz nawias okrągły liczbaTest zamknij nawias okrągły średnik. Linia 24. return 0 średnik. Linia 25. zamknij nawias klamrowy.

Konwersja części ułamkowej

Konwersja części ułamkowej z systemu binarnego na dziesiętny przebiega bardzo podobnie do przekształcania części całkowitej. Mnożymy kolejne bity przez wagi pozycji, jednak tym razem są one kolejnymi potęgami odwrotności podstawy systemu, czyli liczby 2.

Posłużmy się przykładem:

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

Mnożymy kolejne bity (zaczynając od bitu umieszczonego skrajnie po lewej stronie) przez wagę pozycji, czyli przez kolejne odwrotności potęgi liczby 2 (zaczynając od 2Indeks górny -1). Następnie sumujemy iloczyny częściowe. Tak otrzymany wynik jest ułamkiem zapisanym w systemie dziesiętnym.

Słownik

najmłodszy bit
najmłodszy bit

bit o najmniejszej wadze, najbardziej wysunięty na prawo

najstarszy bit
najstarszy bit

bit o największej wadze, najbardziej wysunięty na lewo