Codziennie posługujemy się systemem dziesiętnym zwanym inaczej decymalnym. Jest to system pozycyjny co oznacza, że liczba składa się z cyfr, których wartość zależy od pozycji oraz podstawy systemu. Rozpatrzmy przykładowo liczbę 123. System dziesiętny ma podstawę 10 czyli możemy liczbę zapisać jako:
123 = 100 + 20 + 3 = 1·102 + 2·10 + 3·100
Łatwo zauważyć, że cyfra na i-tej pozycji od prawej strony ma wartość i-ta cyfra pomnożona przez 10 do i-1.
System pozycyjny może mieć dowolną podstawę n. Oznacza to, że na dowolnej pozycji mamy n różnych sposobów zapisania cyfry. Rezultatem tego jest, że liczba na i-tej pozycji od prawej strony ma wartość i-ta cyfra pomnożona przez n do i-1. W celu odróżnienia liczb w różnych system zapisach przyjmuje się, że liczba a o bazie n zapisuje się jako an.
System | Inaczej | Podstawa | Cyfry | Przykład użycia |
---|---|---|---|---|
dwójkowy | binarny | 2 | 0, 1 | system binarny jest podstawą wszystkiego związanego z informatyką |
ósemkowy | oktalny | 8 | 0 - 7 | w system UNIX do reprezentowania poziomu dostępu do pliku |
szesnastkowy | heksadecymalny | 16 | 0 - 9, A - F | określanie koloru podczas stylizowania strony |
Weźmy liczbę a z systemu dziesiętnego. Chcąc przeliczyć ją do innego systemu o podstawie n należy:
Weźmy przykładowo liczbę 21, które chcemy przeliczyć na system binarny:
Iteracja | Operacja | Wynik | Aktualna liczba |
---|---|---|---|
#1 | 21 / 2 | 10 r. 1 | 1 |
#2 | 10 / 2 | 5 r. 0 | 01 |
#3 | 5 / 2 | 2 r. 1 | 101 |
#4 | 2 / 2 | 1 r. 0 | 0101 |
#5 | 1 / 2 | 0 r. 1 | 10101 |
Liczba a wynosi już 0, więc nie wykonujemy iteracji #6. W ten sposób odczytujemy, że 2110 = 101012.
Weźmy liczbę a o bazie n. Chcąc przeliczyć ją do systemu dziesiętnego należy zsumować wartości wszystkich cyfr liczby pamiętając, że i-ta cyfra ma wartość i-tej cyfry pomnożona przez ni-1.
Weźmy przykładowo 101213. Chcąc przeliczyć wyliczamy kolejne pozycje:1·34 + 0·33 + 1·32 + 2·3 + 1·30 = 81 + 0 + 9 + 6 + 1 = 97. Z tego możemy odczytać, że 101213 = 9710.
Załóżmy, że mamy liczbę a z systemu m i chcemy przeliczyć ją na system n. Dokonujemy tego:
Przykładowo chcemy przeliczyć 183 na system ósemkowy:
183 = 1·3 + 8 = 1110
Iteracja | Krok 1 | Krok 2 | Aktualna liczba |
---|---|---|---|
#1 | 11 / 8 | 1 r. 3 | 3 |
#2 | 1 / 8 | 0 r. 1 | 13 |
Z tego odczytujemy, że 183 = 138.
Algorytm wygląda następująco:
Przykładowo zamienimy liczbę 101011112:
Krok | Liczba | ||
---|---|---|---|
#0 | 101011112 | ||
#1 | 0102 | 1012 | 1112 |
#2 | 210 | 510 | 710 |
#3 | 2578 |
Algorytm wygląda następująco:
Przykładowo zamienimy liczbę 2116:
Krok | Liczba | |
---|---|---|
#0 | 2116 | |
#1 | 210 | 110 |
#2 | 00102 | 01012 |
#3 | 1001012 |
C++ pozwala wprowadzać bezpośrednio liczby w systemie ósemkowym, dziesiętnym i szesnastkowym. System dziesiętny wprowadzamy bez zastanowienia:
W przypadku, gdy chcemy wprowadzić liczbę w systemie ósemkowym to na początku liczby używamy 0:
Z kolei dla systemu szesnastkowego jest to 0x:
Ze względu na różne liczby to będziemy przechowywać ich wartości w tablicy char*. W ten sposób będziemy mogli wprowadzić liczbę nawet w systemie szesnastkowym. Taki sposób zapisu nie pozwala na wykonywanie operacji arytmetycznych, ponieważ każda cyfra będzie miała wartość ASCII, a nie dziesiętną, dlatego stworzymy funkcję pomocniczą getIntValue().
(2.) Jeśli znak jest cyfrą to (2.) zwracamy pozycję znaku minus pozycję znaku 0. (3.) Jeśli znak to litera od A do F to (4.) zwracamy pozycję znaku - pozycją znaku A i dodajemy 10, ponieważ A ma wartość dziesiętną 10 w systemie szesnastkowym.
Potrzebujemy jeszcze funkcji, która na podstawie wartości cyfry określi jej reprezentacje przy pomocy znaku:
Jako argumenty otrzymamy liczbę a jako char* oraz jej system n jako int. Naszym zadaniem jest zwrócenie wartości w systemie dziesiętnym.
(2.) Liczbę w systemie dziesiętnym przechowamy w standardowej zmiennej int. Dalej (3.) Dla każdej cyfry w liczbie - zaczynając od najmniej znaczącej, czyli od pierwszej od prawej: (4.) Wyliczamy wartość cyfry na pozycji i i o tyle zwiększamy liczba. (5.) Zwiększamy potęgę, aby w następnym kroku prawidłowo wyliczyć wartość cyfry na następnej pozycji. Na koniec (7.) zwracamy liczba.
Liczbę wynikową zapiszemy w tablicy char*, dlatego na początek obliczymy długość tekstu wynikowego:
(2.) dl przechowa nam długość tekstu wynikowego, a (2.) pot pomoże nam określić jak dużą potęgę znajdziemy w konwertowanej liczbie. (4.) Dopóki potęga jest niższa od liczby to oznacza to, że w podanej długości nie zmieścimy liczby wynikowej, więc (5.) obliczamy kolejną potęge i (6.) zwiększamy długość tekstu, aż (4.) pot będzie większa od n.
(8.) Alokujemy pamięć pod tekst wynikowy. (9.) Znamy długość tekstu wynikowego, więc tyle wykonamy iteracji pętli for, gdzie (10.) Obliczymy resztę z dzielenia w i-tym kroku i zapiszemy od wynik oraz podzielimy a przez n. Nie martwimy się o część ułamkową, ponieważ dzielenie liczb całkowitych da liczbę całkowitą. Na koniec (13.) dopisujemy znak końca danych i (14.) zwracamy wynik.
Poniższa funkcja main() prezentuje przykładowe zastosowanie napisanych funkcji:
Dostosuj funkcje getIntValue() oraz getCharValue(), aby można było wykonać konwersję z /do systemu osiemnastkowego
Dopisz funkcję goodNumSys(), która sprawdzi czy dana liczba jest prawidłowo zapisana w danym systemie.