System Ósemkowy (Oktalny) na Maturze z Informatyki
System ósemkowy (oktalny) to system liczbowy o podstawie 8. Oznacza to, że używa tylko ośmiu cyfr: 0, 1, 2, 3, 4, 5, 6 i 7. Jest on znacznie rzadszy niż system binarny czy szesnastkowy, ale działa na identycznej zasadzie systemów pozycyjnych. Historycznie był popularny w niektórych wczesnych systemach komputerowych (jak PDP-8), ponieważ jest bardzo łatwy do zamiany na system binarny. Dzieje się tak, ponieważ podstawa systemu (8) jest potęgą dwójki ($2^3 = 8$). Pozwala to na prostą konwersję przez grupowanie bitów trójkami. Zamiast długiego ciągu binarnego `110101011_2`, można go znacznie krócej zapisać jako `653_8`.
Dlaczego to ważne? Na maturze jest on o wiele mniej popularny niż BIN i HEX. Jednak zasady jego konwersji są identyczne jak dla innych systemów. Może pojawić się w zadaniach 'na papierze' (np. porównywanie liczb w różnych systemach) lub jako część zadania o szybkiej konwersji (np. BIN <-> OCT). W Pythonie i C++ istnieją wbudowane narzędzia do jego obsługi, więc warto je znać.
Teoria
System ósemkowy (oktalny) to system pozycyjny o podstawie 8. Używa cyfr od 0 do 7. Wartość liczby to suma jej cyfr pomnożonych przez odpowiednie wagi, czyli potęgi liczby 8.
Jak to działa?
- **1. Ósemkowy (OCT) -> Dziesiętny (DEC)**: Mnożenie przez wagi (potęgi 8).
- Przykład: `127_8` = $1 * 8^2 + 2 * 8^1 + 7 * 8^0 = 1 * 64 + 2 * 8 + 7 * 1 = 64 + 16 + 7 = 87_10$.
- **2. Dziesiętny (DEC) -> Ósemkowy (OCT)**: Dzielenie przez 8 i zbieranie reszt (od końca).
- Przykład dla `87_10`:
- `87 // 8 = 10` reszty `7`
- `10 // 8 = 1` reszty `2`
- `1 // 8 = 0` reszty `1`
- Czytamy reszty od dołu do góry: `127_8`.
- **3. Ósemkowy (OCT) <-> Binarny (BIN) (Szybka konwersja)**: Grupowanie po 3 bity!
- Każda cyfra ósemkowa idealnie odpowiada 3 bitom ($2^3 = 8$):
- 0=000, 1=001, 2=010, 3=011, 4=100, 5=101, 6=110, 7=111
- BIN -> OCT: `101 | 110 | 001` (grupujemy po 3 od prawej). `101_2 = 5_8`. `110_2 = 6_8`. `001_2 = 1_8`. Wynik: `561_8`.
- OCT -> BIN: `561_8`. `5_8 = 101_2`. `6_8 = 110_2`. `1_8 = 001_2`. Wynik: `101110001_2`.
Złożoność: Algorytmy konwersji są bardzo szybkie. Zamiana DEC -> OCT (dzielenie przez 8) ma złożoność O(log n), proporcjonalną do liczby cyfr wynikowej. Zamiana OCT -> DEC ma złożoność O(k), gdzie 'k' to liczba cyfr ósemkowych.
Implementacja
Konwersje w Pythonie (Funkcje wbudowane)
Python# ---- Z ÓSEMKOWEGO na DZIESIĘTNY ----
# Używamy int(string_liczby, 8)
oct_na_dec = int("127", 8)
print(f"'127' (oct) to {oct_na_dec} (dec)") # 87
# ---- Z DZIESIĘTNEGO na ÓSEMKOWY ----
# Używamy oct()
dec_na_oct = oct(87)
print(f"87 (dec) to {dec_na_oct}") # '0o127'
# Jak pozbyć się prefiksu '0o'?
print(f"Czysty ósemkowy: {oct(87)[2:]}") # '127'
# Prefiks do zapisu liczby w kodzie:
liczba_osemkowa = 0o127 # To jest to samo co 87
print(f"Zmienna 0o127 to dziesiętnie {liczba_osemkowa}")Na maturze to najszybszy sposób. Funkcja `int(string, 8)` zamienia string ósemkowy na liczbę dziesiętną. Funkcja `oct(n)` zamienia liczbę dziesiętną na string ósemkowy z prefiksem `0o` (zero i małe 'o'), który obcinamy przez `[2:]`.
Konwersje w C++ (stoi, stringstream)
C++#include <iostream>
#include <string>
#include <sstream> // dla stringstream (dec na oct)
using namespace std;
int main() {
// ---- Z ÓSEMKOWEGO na DZIESIĘTNY ----
// Używamy stoi(string, nullptr, 8)
string oct_str = "127";
int oct_na_dec = stoi(oct_str, nullptr, 8);
cout << "'127' (oct) to " << oct_na_dec << " (dec)" << endl; // 87
// ---- Z DZIESIĘTNEGO na ÓSEMKOWY ----
// Używamy stringstream z manipulatorem 'oct'
stringstream ss;
ss << oct << 87;
string dec_na_oct = ss.str();
cout << "87 (dec) to " << dec_na_oct << " (oct)" << endl; // 127
return 0;
}W C++ do zamiany stringa na int używamy `stoi(str, _, 8)` z biblioteki `<string>`. Do zamiany liczby dziesiętnej na string ósemkowy najwygodniej użyć `stringstream` z manipulatorem `std::oct`.
Przykładowe Zadania Maturalne
W pliku 'liczby_osemkowe.txt' znajduje się 200 wierszy, a w każdym jedna liczba zapisana w systemie ósemkowym. Napisz program, który znajdzie i wypisze tę liczbę (w postaci ósemkowej), która po konwersji 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, 8)`, w C++ `stoi(string, _, 8)`), aby zamienić ósemkowy string na liczbę dziesiętną. Trzymaj w zmiennej 'max_dec' największą wartość dziesiętną i w 'max_oct_str' odpowiadający jej string.
Pokaż szkic rozwiązania
1. Otwórz plik 'liczby_osemkowe.txt' do odczytu. 2. Zainicjuj `max_dec = -1` oraz `max_oct_str = ""`. 3. Dla każdej linii w pliku: a. Wczytaj string: `oct_str = linia.strip()`. b. Przekonwertuj na liczbę dziesiętny: `dec_val = int(oct_str, 8)`. c. Sprawdź: `if dec_val > max_dec:` d. ` max_dec = dec_val` e. ` max_oct_str = oct_str` 4. Po pętli wypisz `max_oct_str`.
Oryginalne zadanie dotyczyło systemów o podstawie 3 i 9. Taka sama zasada szybkiej konwersji dotyczy systemów o podstawie 2 i 8. Uzupełnij tabelę, dokonując szybkiej konwersji: `71_8 = ?_2` oraz `110101_2 = ?_8`.
Wskazówka: Szybka konwersja BIN <-> OCT polega na grupowaniu bitów po 3 ($2^3=8$).
Pokaż szkic rozwiązania
1. **Zamiana `71_8` na BIN (`?_2`)**: a. Zamień *każdą* cyfrę ósemkową na 3 bity. b. `7_8` = `111_2`. c. `1_8` = `001_2` (ważne dopełnienie do 3 bitów!). d. Połącz bity: `111` + `001` = `111001_2`. e. Odpowiedź: `111001_2`. 2. **Zamiana `110101_2` na OCT (`?_8`)**: a. Grupuj bity po 3, *zaczynając od prawej strony*. b. `110 | 101`. c. Zamień każdą grupę na cyfrę ósemkową: d. `110_2` = $4 + 2 = 6_8$. e. `101_2` = $4 + 1 = 5_8$. f. Odpowiedź: `65_8`.
Częste Błędy
❌ Błąd `ValueError` (Python) lub zły wynik `stoi` (C++)
Próba konwersji liczby zawierającej niedozwolone cyfry, np. `int('128', 8)`. Cyfra 8 nie istnieje w systemie ósemkowym (tylko 0-7).
Poprawka: Pamiętaj, że system ósemkowy używa *tylko* cyfr od 0 do 7. Każda cyfra 8 lub 9 w danych wejściowych spowoduje błąd.
❌ Mylenie `oct()` z `int(s, 8)`
`oct(n)` zamienia liczbę *dziesiętną* `n` na string ósemkowy (np. `oct(87)` -> `'0o127'`). `int(s, 8)` zamienia *string* ósemkowy `s` na liczbę dziesiętną (np. `int('127', 8)` -> `87`).
Poprawka: Pamiętaj, w którą stronę konwertujesz. `int()` służy do zamiany *na* system dziesiętny.
❌ Błędne grupowanie przy konwersji BIN <-> OCT
Użycie grupowania po 4 bity (jak w HEX) zamiast po 3 bity.
Poprawka: Zapamiętaj: BIN<->HEX to 4 bity ($2^4=16$). BIN<->OCT to 3 bity ($2^3=8$).
❌ Zapominanie o prefiksie '0o' w Pythonie
Funkcja `oct(n)` w Pythonie zwraca string z prefiksem, np. `'0o127'`. Jeśli chcesz czystą liczbę, musisz go obciąć.
Poprawka: Użyj cięcia (slicingu): `oct(n)[2:]`.
Kluczowe Wnioski
- System ósemkowy (oktalny) ma podstawę 8 i używa cyfr 0-7.
- Konwersja OCT -> DEC: Mnożenie przez potęgi 8 (np. `12_8 = 1*8^1 + 2*8^0 = 10_10`).
- Konwersja DEC -> OCT: Dzielenie przez 8 i zbieranie reszt od końca.
- Szybka konwersja BIN <-> OCT: Grupujemy bity po 3 (np. `111_2 = 7_8`, `101_2 = 5_8`).
- Python: `int('127', 8)` zamienia string ósemkowy na `int`. `oct(87)` zamienia `int` na string ósemkowy (`'0o127'`).
- C++: `stoi("127", nullptr, 8)` zamienia string ósemkowy na `int`. `stringstream ss; ss << oct << 87;` zamienia `int` na string ósemkowy.
Najczęściej Zadawane Pytania
❓ Dlaczego `010` w C++ to `8`?
W C++ (oraz starszych wersjach Pythona), prefiks `0` (pojedyncze zero) przed liczbą oznaczał, że jest ona zapisana w systemie ósemkowym. Dlatego `010` było traktowane jako `10_8`, co równa się `1*8^1 + 0*8^0 = 8_10`. W nowym Pythonie 3 to powodowało błędy, więc wprowadzono jawny prefiks `0o` (np. `0o10`).
❓ Czy na maturze muszę znać system ósemkowy?
Jest znacznie rzadszy niż binarny i szesnastkowy, ale zasady konwersji są identyczne jak dla innych systemów. Zrozumienie go pokazuje pełne opanowanie systemów liczbowych. Jest to system 'łatwy', jeśli znasz już BIN i HEX.
❓ Jak działa szybka konwersja BIN <-> OCT?
Działa, bo $2^3 = 8$. Oznacza to, że każda cyfra ósemkowa (0-7) idealnie mapuje się na 3-bitowy ciąg binarny (od 000 do 111). Możesz zamieniać liczbę 'fragmentami' po 3 bity, co jest znacznie szybsze niż konwersja przez system dziesiętny.
❓ Jak w C++ zamienić `int` na ósemkowy string *bez* `stringstream`?
Musisz napisać algorytm ręcznie, używając pętli `while (n > 0)`, operatora `% 8` (do pobrania reszty) i `/ 8` (do skrócenia liczby). Reszty zbierasz do stringa (konwertując `int` na `char`), a na końcu musisz ten string odwrócić (np. funkcją `std::reverse`).
Chcesz opanować wszystkie tematy maturalne?
Dołącz do kursu i zyskaj dostęp do interaktywnych lekcji, edytora kodu i setek zadań.