Konwersja Systemów Liczbowych (Binarny, Dziesiętny, Szesnastkowy)
Systemy liczbowe to fundament informatyki. Na co dzień używamy systemu **dziesiętnego (DEC)**, opartego na 10 cyfrach (0-9). Komputery wewnątrz działają wyłącznie na systemie **binarnym (BIN)**, czyli na dwóch cyfrach (0 i 1). Z kolei system **szesnastkowy (HEX)**, oparty na 16 symbolach (0-9 oraz A-F), jest używany przez programistów jako wygodny 'skrót' do zapisu długich ciągów binarnych (np. do opisu kolorów, #FF0000, lub adresów pamięci). Zrozumienie, jak te systemy działają i jak płynnie przeliczać liczby między nimi, to absolutna konieczność, by zrozumieć, co tak naprawdę robi komputer.
Dlaczego to ważne? Na maturze zadania z systemów liczbowych pojawiają się *zawsze*. Mogą to być zadania 'na papierze', gdzie trzeba ręcznie przeliczyć wartości (jak w zadaniu z XORem), zadania z liczbami binarnymi w plikach tekstowych (np. 'policz, ile liczb ma więcej jedynek niż zer') lub zadania wymagające operacji na bitach. Umiejętność zamiany liczby dziesiętnej na binarną i odwrotnie to podstawa do rozwiązania tych problemów.
Teoria
Każdy system liczbowy opiera się na 'podstawie'. W dziesiętnym podstawą jest 10, w binarnym 2, w szesnastkowym 16. Wartość liczby to suma jej cyfr pomnożonych przez odpowiednie wagi, czyli potęgi podstawy systemu.
Jak to działa?
- **1. Dowolny system -> Dziesiętny (DEC)**: Mnożenie przez wagi.
- Przykład BIN -> DEC: `1011_2` = $1 * 2^3 + 0 * 2^2 + 1 * 2^1 + 1 * 2^0 = 8 + 0 + 2 + 1 = 11_10$.
- Przykład HEX -> DEC: `A1_16` = $10 * 16^1 + 1 * 16^0 = 160 + 1 = 161_10$. (Pamiętaj: A=10, B=11, C=12, D=13, E=14, F=15).
- Python: `int('1011', 2)` da `11`. `int('A1', 16)` da `161`.
- **2. Dziesiętny (DEC) -> Dowolny system**: Dzielenie przez podstawę i zbieranie reszt.
- Przykład DEC -> BIN (dla 11_10):
- `11 // 2 = 5` reszty `1`
- `5 // 2 = 2` reszty `1`
- `2 // 2 = 1` reszty `0`
- `1 // 2 = 0` reszty `1`
- Czytamy reszty od dołu do góry: `1011_2`.
- Python: `bin(11)` da `'0b1011'`. `hex(161)` da `'0xa1'`.
- **3. Binarny (BIN) <-> Szesnastkowy (HEX) (Szybka konwersja)**: Grupowanie po 4 bity.
- Każde 4 bity (cyfry binarne) odpowiadają dokładnie jednej cyfrze szesnastkowej ($2^4 = 16$).
- BIN -> HEX: `1011 | 0001` (grupujemy po 4 od prawej). `1011_2 = 11_10 = B_16`. `0001_2 = 1_10 = 1_16`. Wynik: `B1_16`.
- HEX -> BIN: `B1_16`. `B_16 = 1011_2`. `1_16 = 0001_2` (uzupełniamy do 4 bitów!). Wynik: `10110001_2`.
Złożoność: Ręczny algorytm zamiany DEC -> BIN (dzielenie przez 2) ma złożoność O(log n), ponieważ liczba kroków (dzieleń) zależy od liczby bitów, a nie od wartości 'n'. Algorytm BIN -> DEC ma złożoność O(k), gdzie 'k' to liczba cyfr (bitów) w liczbie.
Implementacja
Konwersje w Pythonie (Funkcje wbudowane)
Python# ---- Z dowolnego systemu NA DZIESIĘTNY ----
# Używamy int(string_liczby, podstawa)
bin_na_dec = int("1011", 2)
print(f"'1011' (bin) to {bin_na_dec} (dec)") # 11
hex_na_dec = int("FF", 16)
print(f"'FF' (hex) to {hex_na_dec} (dec)") # 255
# ---- Z DZIESIĘTNEGO na dowolny system ----
# Używamy bin(), hex(), oct()
dec_na_bin = bin(11)
print(f"11 (dec) to {dec_na_bin}") # '0b1011'
dec_na_hex = hex(255)
print(f"255 (dec) to {dec_na_hex}") # '0xff'
# Jak pozbyć się prefiksów '0b' i '0x'?
print(f"Czysty binarny: {bin(11)[2:]}") # '1011'
print(f"Czysty hex: {hex(255)[2:]}") # 'ff'Na maturze to jest najszybszy i najlepszy sposób. Funkcja `int(string, podstawa)` jest kluczowa. Pamiętaj, że `bin()` i `hex()` zwracają stringi z prefiksami '0b' i '0x', które można obciąć za pomocą `[2:]`.
Algorytm: Ręczna zamiana DEC -> BIN
Pythondef dec_na_bin(n):
if n == 0:
return "0"
binarny_str = ""
liczba = n
while liczba > 0:
reszta = liczba % 2
binarny_str += str(reszta)
liczba = liczba // 2
# Reszty są zbierane od końca, więc musimy odwrócić string
return binarny_str[::-1]
print(f"11 (dec) to ręcznie {dec_na_bin(11)} (bin)") # 1011To jest implementacja algorytmu 'dziel i zbieraj reszty'. Używamy pętli `while`, operatora modulo `% 2` (po resztę) i dzielenia całkowitego `// 2` (by skrócić liczbę). Na końcu odwracamy string, bo reszty zbieraliśmy od najmniej znaczącej.
Konwersje w C++ (std::stoi, std::bitset, stringstream)
C++#include <iostream>
#include <string>
#include <sstream> // dla stringstream (dec na hex)
#include <bitset> // dla bitset (dec na bin)
using namespace std;
int main() {
// ---- Z dowolnego systemu NA DZIESIĘTNY ----
// Używamy stoi(string, nullptr, podstawa)
string bin_str = "1011";
int bin_na_dec = stoi(bin_str, nullptr, 2);
cout << "'1011' (bin) to " << bin_na_dec << " (dec)" << endl; // 11
string hex_str = "FF";
int hex_na_dec = stoi(hex_str, nullptr, 16);
cout << "'FF' (hex) to " << hex_na_dec << " (dec)" << endl; // 255
// ---- Z DZIESIĘTNEGO na dowolny system ----
// DEC -> BIN (bitset)
string dec_na_bin = bitset<8>(11).to_string(); // <8> to liczba bitów
cout << "11 (dec) to " << dec_na_bin << " (bin)" << endl; // 00001011
// DEC -> HEX (stringstream)
stringstream ss;
ss << hex << 255;
string dec_na_hex = ss.str();
cout << "255 (dec) to " << dec_na_hex << " (hex)" << endl; // ff
return 0;
}W C++ jest to trochę bardziej skomplikowane. Do zamiany `string` na `int` używamy `stoi(str, _, podstawa)` z biblioteki `<string>`. Do zamiany `int` na `string` binarny/szesnastkowy najwygodniej użyć `bitset` (dla bin) lub `stringstream` (dla hex).
Przykładowe Zadania Maturalne
W pliku 'liczby_binarne.txt' znajduje się 200 liczb binarnych, każda w osobnej linii. Napisz program, który znajdzie i wypisze tę liczbę (w postaci binarnej), która po zamianie na system dziesiętny jest największa.
Wskazówka: Nie musisz implementować algorytmu ręcznie. Wczytaj każdą linię (string) z pliku. Użyj wbudowanej funkcji (w Pythonie `int(string, 2)`) aby zamienić binarny string na liczbę dziesiętną. Trzymaj w zmiennej 'max_dec' największą dotychczasową wartość dziesiętną oraz w 'max_bin_str' odpowiadający jej string binarny.
Pokaż szkic rozwiązania
1. Otwórz plik 'liczby_binarne.txt' do odczytu. 2. Zainicjuj `max_dec = -1` oraz `max_bin_str = ""`. 3. Dla każdej linii w pliku: a. Wczytaj string: `bin_str = linia.strip()`. b. Przekonwertuj na liczbę dziesiętną: `dec_val = int(bin_str, 2)`. c. Sprawdź: `if dec_val > max_dec:` d. ` max_dec = dec_val` e. ` max_bin_str = bin_str` 4. Po pętli wypisz `max_bin_str`.
Oblicz (123_10 XOR 101101_2) XOR 2D_16. Wynik podaj w systemie dziesiętnym.
Wskazówka: To zadanie 'na papierze'. Aby wykonać operacje bitowe XOR, musisz sprowadzić wszystkie trzy liczby do tego samego systemu. Najłatwiej zamienić je wszystkie na system dziesiętny, wykonać operacje XOR (oznaczaną w Pythonie jako `^`), a na końcu podać wynik.
Pokaż szkic rozwiązania
1. **Liczba 1: `123_10`**. Jest już w systemie dziesiętnym. Wartość: 123. 2. **Liczba 2: `101101_2`**. Zamiana BIN -> DEC: $1*2^5 + 0*2^4 + 1*2^3 + 1*2^2 + 0*2^1 + 1*2^0 = 32 + 0 + 8 + 4 + 0 + 1 = 45_10$. 3. **Liczba 3: `2D_16`**. Zamiana HEX -> DEC: $2 * 16^1 + 13 * 16^0 = 32 + 13 = 45_10$. (Pamiętaj: D = 13). 4. **Obliczenia (krok po kroku):** a. Pierwszy XOR: `123_10 XOR 45_10`. b. `123_10 = 1111011_2` c. `45_10 = 0101101_2` (uzupełniamy zerem z przodu) d. `1111011 XOR 0101101 = 1010110_2`. e. `1010110_2 = 64 + 16 + 4 + 2 = 86_10`. f. Drugi XOR: `86_10 XOR 45_10` (bo `2D_16 = 45_10`). g. `86_10 = 1010110_2` h. `45_10 = 0101101_2` i. `1010110 XOR 0101101 = 1111011_2`. 5. **Zamiana wyniku na DEC**: `1111011_2 = 64 + 32 + 16 + 8 + 0 + 2 + 1 = 123_10`. 6. **Odpowiedź**: 123.
Częste Błędy
❌ Python: `int(1011, 2)` zamiast `int('1011', 2)`
Funkcja `int()` do konwersji oczekuje *stringa* (tekstu) jako pierwszego argumentu. Przekazanie jej liczby `1011` (traktowanej jako dziesiętna) spowoduje błąd lub (co gorsza) zły wynik.
Poprawka: Zawsze przekazuj liczbę w innym systemie jako string: `int('1011', 2)`.
❌ Zapominanie o prefiksach `0b` i `0x` w Pythonie
Funkcje `bin()` i `hex()` zwracają stringi z prefiksami, np. `'0b1011'`. Jeśli spróbujesz użyć tego stringa w dalszych obliczeniach (np. zliczyć jedynki), prefiks będzie przeszkadzał.
Poprawka: Do czystej postaci binarnej/szesnastkowej używaj cięcia: `bin(n)[2:]` lub `hex(n)[2:]`.
❌ Dec -> Bin: Odwrócenie kolejności reszt
Algorytm `n % 2` i `n // 2` generuje bity *od końca* (od najmniej znaczącego do najbardziej). Jeśli po prostu skleisz je po kolei, dostaniesz liczbę 'od tyłu'.
Poprawka: Musisz dodawać reszty na *początek* budowanego stringa (`wynik = str(reszta) + wynik`) lub zebrać je w liście i na końcu ją odwrócić (`wynik.reverse()`).
❌ BIN <-> HEX: Błędne grupowanie
Zamiana `A1_16` na `1010` (dla A) i `1` (dla 1). Poprawnie powinno być `1` -> `0001`. Musisz dopełniać bity do 4.
Poprawka: Zawsze grupuj po 4 bity, dopełniając zerami z lewej, jeśli trzeba: `A_16` -> `1010`, `1_16` -> `0001`. Łącznie: `10100001_2`.
❌ Mylenie cyfr HEX (D vs B)
Częsty błąd 'na papierze' to pomyłka: A=10, B=11, C=12, D=13, E=14, F=15. Łatwo pomylić B z D.
Poprawka: Warto zapisać to sobie na brudnopisie podczas egzaminu. Można też szybko sprawdzić w kalkulatorze systemowym.
Kluczowe Wnioski
- Trzy kluczowe systemy: **Dziesiętny** (podstawa 10), **Binarny** (podstawa 2), **Szesnastkowy** (podstawa 16, 0-9 i A-F).
- **Any -> DEC**: Mnożenie przez potęgi podstawy (np. $101_2 = 1*2^2 + 0*2^1 + 1*2^0 = 5_10$).
- **DEC -> Any**: Dzielenie przez podstawę i zbieranie reszt *od końca*.
- **BIN <-> HEX**: Szybka konwersja przez grupowanie bitów po 4 ($2^4 = 16$).
- W Pythonie `int(string, podstawa)` to Twój najlepszy przyjaciel (np. `int('FF', 16)`).
- W Pythonie `bin(n)` i `hex(n)` zwracają stringi z prefiksami `0b` i `0x`.
- Zadania maturalne często wymagają konwersji, aby wykonać operacje bitowe (jak XOR).
Najczęściej Zadawane Pytania
❓ Po co nam system szesnastkowy (HEX)?
Jest to wygodny dla człowieka 'skrót' do zapisu długich liczb binarnych. Jeden bajt (8 bitów), np. `10101111`, można zapisać jako dwie cyfry HEX: `AF`. Jest to dużo czytelniejsze. Używa się go powszechnie do zapisu kolorów (np. `#FF0000` to 255-R, 0-G, 0-B) i adresów pamięci.
❓ Jak szybko zamienić `110101_2` na dziesiętny?
Sumuj potęgi dwójki tam, gdzie jest jedynka, licząc od prawej (od $2^0$): $110101_2 = 2^5 + 2^4 + 0 + 2^2 + 0 + 2^0 = 32 + 16 + 4 + 1 = 53$.
❓ Czy na maturze mogę używać wbudowanych funkcji `bin()`, `hex()`, `int(s, 2)`?
Tak. Są to funkcje wbudowane w Pythona i są częścią standardowej biblioteki, która jest dozwolona. Używanie ich jest wręcz zalecane, aby oszczędzać czas (chyba że zadanie wprost każe zaimplementować algorytm konwersji).
❓ Jak w Pythonie przekonwertować liczbę dziesiętną na string binarny bez prefiksu '0b'?
Użyj `bin(liczba)[2:]`. Funkcja `bin()` zwraca string, a `[2:]` to 'cięcie' (slicing), które bierze string od trzeciego znaku (indeks 2) do końca, pomijając pierwsze dwa znaki ('0' i 'b').
Chcesz opanować wszystkie tematy maturalne?
Dołącz do kursu i zyskaj dostęp do interaktywnych lekcji, edytora kodu i setek zadań.