średniProgramowaniePythonC++

Operatory Bitowe (&, |, ^, <<, >>) na Maturze z Informatyki

15 min czytania
Python, C++
Zaktualizowano: 4.11.2025

Operatory bitowe to specjalne operatory, które nie działają na liczbie jako całości (np. 123), ale bezpośrednio na jej *bitach* (czyli jej reprezentacji binarnej, np. 1111011). Zamiast wykonywać dodawanie czy mnożenie, wykonują operacje logiczne (AND, OR, XOR) na każdej parze bitów jednocześnie. Na przykład, porównując 5 (101) i 3 (011), porównują pierwszy bit z pierwszym, drugi z drugim itd. Są to operacje 'niskopoziomowe', co oznacza, że są *ekstremalnie* szybkie – często wykonywane w jednym cyklu procesora. Na maturze pozwalają na sprytne i wydajne rozwiązywanie niektórych zadań, zwłaszcza tych 'na papierze'.

Dlaczego to ważne? Musisz znać operatory bitowe, aby rozwiązać specyficzne zadania maturalne, które wprost o nie pytają (jak zadanie z XOR w 2023 roku). Są też fundamentem do zrozumienia, jak komputer przechowuje dane, jak działają maski bitowe (np. do sprawdzania, czy dany bit jest 'zapalony') oraz do wykonywania superszybkich operacji mnożenia i dzielenia przez potęgi dwójki (za pomocą przesunięć bitowych).

Teoria

Główna idea polega na traktowaniu liczb jako ciągów bitów. Operacja bitowa jest stosowana 'kolumnowo' do każdej pary bitów. Np. dla `5 & 3`: ` 101` (5) `& 011` (3) `----` ` 001` (1) Dzieje się tak, bo: `1&0=0`, `0&1=0`, `1&1=1`.

Jak to działa?

  1. `&` (Bitowe AND): Zwraca 1 *tylko* jeśli oba bity na tej samej pozycji to 1.
  2. `|` (Bitowe OR): Zwraca 1 jeśli *przynajmniej jeden* z bitów na tej pozycji to 1.
  3. `^` (Bitowe XOR - 'albo'): Zwraca 1 jeśli bity na tej pozycji są *różne*.
  4. `<<` (Przesunięcie w lewo): Przesuwa wszystkie bity w lewo, dopisując zera z prawej. `x << n` to szybkie mnożenie $x * 2^n$.
  5. `>>` (Przesunięcie w prawo): Przesuwa wszystkie bity w prawo, 'wyrzucając' te z prawej. `x >> n` to szybkie dzielenie całkowite $x // 2^n$.
  6. `~` (Bitowe NOT): Odwraca wszystkie bity (0 na 1, 1 na 0). Rzadziej używane na maturze ze względu na komplikacje z liczbami ujemnymi (kod U2).

Złożoność: Wszystkie operatory bitowe są operacjami o czasie stałym, O(1) (lub O(k) gdzie k to liczba bitów w liczbie, np. 32/64, co jest stałą). Są to jedne z najszybszych operacji, jakie może wykonać procesor.

Implementacja

Operatory AND, OR, XOR

Python
a = 5 # binarnie: 101
b = 3 # binarnie: 011 (uzupełniamy zerem z przodu)

print(f"a = {a:03b}, b = {b:03b}") # :03b - binarnie, z zerami do 3 cyfr

# AND (&): 101 & 011 = 001
print(f"a & b = {a & b} ({a & b:03b})") # Wynik: 1 (001)

# OR (|): 101 | 011 = 111
print(f"a | b = {a | b} ({a | b:03b})") # Wynik: 7 (111)

# XOR (^): 101 ^ 011 = 110
print(f"a ^ b = {a ^ b} ({a ^ b:03b})") # Wynik: 6 (110)

To podstawowe użycie. Python (i C++) wykonuje operacje na bitach. `101 & 011` daje `001`, ponieważ tylko ostatnia kolumna miała `1 & 1`. `101 | 011` daje `111`, bo w każdej kolumnie występował przynajmniej jeden bit `1`. Wyniki są pokazane zarówno dziesiętnie, jak i binarnie.

Przesunięcia bitowe (Shift) - Mnożenie i Dzielenie

Python
n = 10 # binarnie: 1010

# Przesunięcie w lewo o 1 (mnożenie przez 2^1 = 2)
# 1010 -> 10100 (z 10 robi się 20)
print(f"{n} << 1 = {n << 1}") # Wynik: 20

# Przesunięcie w lewo o 3 (mnożenie przez 2^3 = 8)
# 1010 -> 1010000 (z 10 robi się 80)
print(f"{n} << 3 = {n << 3}") # Wynik: 80

# Przesunięcie w prawo o 1 (dzielenie całkowite przez 2^1 = 2)
# 1010 -> 101 (z 10 robi się 5)
print(f"{n} >> 1 = {n >> 1}") # Wynik: 5

# Przesunięcie w prawo o 2 (dzielenie całkowite przez 2^2 = 4)
# 1010 -> 10 (z 10 robi się 2)
print(f"{n} >> 2 = {n >> 2}") # Wynik: 2

Przesunięcia bitowe to superszybki sposób na mnożenie i dzielenie przez potęgi dwójki. `n << k` to to samo co `n * (2**k)`. `n >> k` to to samo co `n // (2**k)`.

Wzorzec: Maska bitowa (sprawdzanie bitu)

Python
# Jak sprawdzić, czy 3. bit (licząc od 0) w liczbie n jest '1'?
# 3. bit odpowiada wartości 2^3 = 8 (binarnie: 1000)
# To jest nasza 'maska'

n = 13 # binarnie: 1101
maska = 1 << 3 # To jest 8, czyli binarnie 1000

# Używamy AND. Jeśli wynik jest > 0, to bit był zapalony.
#   1101 (13)
# & 1000 (maska 8)
# ------
#   1000 (8, co jest > 0)
if (n & maska) > 0: 
    print("3. bit jest ustawiony (1)")
else:
    print("3. bit jest 0")

# Sprawdzenie bitu 0 (wartość 2^0 = 1)
if (n & 1) == 0:
    print("Liczba jest parzysta")
else:
    print("Liczba jest nieparzysta")

To najważniejsze zastosowanie operatora `&`. Tworzymy 'maskę' z jedną jedynką na pozycji, którą chcemy sprawdzić (używając przesunięcia `1 << k`). Operacja `n & maska` 'wygasza' wszystkie bity oprócz tego, który nas interesuje. Jeśli wynik jest niezerowy, to bit był ustawiony.

Przykładowe Zadania Maturalne

Matura 2026Zadanie Zadanie Typu Maturalnego 1

Napisz program, który wczyta z pliku 'liczby.txt' 200 liczb całkowitych (każda w nowej linii). Podaj, ile z tych liczb ma *dokładnie jeden* ustawiony bit '1' w swojej reprezentacji binarnej (są to potęgi liczby 2, np. 1, 2, 4, 8, 16...).

Wskazówka: Liczba jest potęgą dwójki (ma jeden bit '1'), jeśli spełnia sprytny warunek bitowy: `n > 0 AND (n & (n - 1)) == 0`. Na przykład dla n=8: `n = 1000`, `n-1 = 0111`. `1000 & 0111 = 0000`. Dla n=6: `n = 110`, `n-1 = 101`. `110 & 101 = 100` (nie jest zerem).

Pokaż szkic rozwiązania
1. Otwórz plik 'liczby.txt'.
2. Zainicjuj `licznik_poteg_dwojki = 0`.
3. Dla każdej linii w pliku:
   a. Wczytaj `n = int(linia.strip())`.
   b. Sprawdź warunek: `if n > 0 and (n & (n - 1)) == 0:`
   c. `  licznik_poteg_dwojki += 1`
4. Wypisz `licznik_poteg_dwojki`.
5. (Alternatywnie: `if bin(n).count('1') == 1:`)
Matura 2023Zadanie 2.4 (Matura Czerwiec 2023)

Oblicz (123_10 XOR 101101_2) XOR 2D_16. Wynik podaj w systemie dziesiętnym.

Wskazówka: To zadanie 'na papierze', które wprost testuje znajomość operatora XOR. Aby je wykonać, musisz sprowadzić wszystkie trzy liczby do jednego, wspólnego systemu (np. dziesiętnego lub binarnego) i wykonać operacje po kolei.

Pokaż szkic rozwiązania
1. Zamień wszystkie liczby na system dziesiętny:
   a. `123_10` = 123.
   b. `101101_2` = $1*32 + 0*16 + 1*8 + 1*4 + 0*2 + 1*1 = 32 + 8 + 4 + 1 = 45$.
   c. `2D_16` = $2*16 + 13*1 = 32 + 13 = 45$ (ponieważ D=13).
2. Wykonaj operacje XOR (w Pythonie/C++ to operator `^`):
   a. Oblicz pierwszy nawias: `123 ^ 45`.
   b. `123` to `1111011_2`.
   c. `45` to `0101101_2`.
   d. `1111011 ^ 0101101 = 1010110_2`.
   e. `1010110_2` to $64 + 16 + 4 + 2 = 86$.
   f. Oblicz drugą operację: `86 ^ 45`.
   g. `86` to `1010110_2`.
   h. `45` to `0101101_2`.
   i. `1010110 ^ 0101101 = 1111011_2`.
3. Zamień wynik z powrotem na dziesiętny (jeśli liczysz binarnie):
   a. `1111011_2` to $64 + 32 + 16 + 8 + 2 + 1 = 123$.
4. Odpowiedź: 123.

Częste Błędy

Mylenie operatorów bitowych (`&`, `|`) z logicznymi (`and`, `or`)

To krytyczny błąd! `if x > 10 and y > 10` (logiczne) sprawdza dwa warunki. `if x & y` (bitowe) wykonuje operację na bitach. `4 and 2` da `True` (bo 2 jest 'prawdziwe'), ale `4 & 2` (`100 & 010`) da `0` (`False`).

Poprawka: Do łączenia warunków `if` używaj `and`, `or`. Do manipulacji bitami używaj `&`, `|`, `^`.

Python: Używanie `^` do potęgowania

W wielu językach (i matematyce) `^` oznacza potęgę. W Pythonie i C++ `^` to **XOR**. Do potęgowania w Pythonie służy operator `**`.

Poprawka: Zapamiętaj: `2 ^ 3` to `1` (bo `10 ^ 11 = 01`), a `2 ** 3` to `8`.

Dziwne wyniki negacji (`~`)

Początkujący wpisuje `~5` (`~101`) i spodziewa się `010` (2). Zamiast tego dostaje `-6`. Dzieje się tak z powodu używania przez komputery kodu uzupełnień do dwóch (U2) do reprezentacji liczb ujemnych.

Poprawka: Unikaj operatora `~` na maturze, jeśli nie jesteś absolutnie pewien, jak działa kod U2. Do wyzerowania bitu lepiej użyć maski z `&` (np. `n & 0b111011`).

Zła kolejność działań (precedens)

Operatory bitowe mają niższą kolejność niż arytmetyczne i czasem niższą niż porównania. Kod `if n & 1 == 0:` może być zinterpretowany jako `if n & (1 == 0):` czyli `if n & 0:`, co jest zawsze fałszem.

Poprawka: Zawsze, *zawsze* używaj nawiasów przy operacjach bitowych: `if (n & 1) == 0:`.

Kluczowe Wnioski

  • Operatory bitowe `&`, `|`, `^` działają na pojedynczych bitach liczby.
  • `&` (AND) - 'zapala' bit, gdy oba są zapalone. Świetne do *sprawdzania* bitów (maskowanie).
  • `|` (OR) - 'zapala' bit, gdy choć jeden jest zapalony. Świetne do *ustawiania* bitów.
  • `^` (XOR) - 'zapala' bit, gdy są różne. Świetne do *przełączania* bitów.
  • `<< k` to szybkie mnożenie przez $2^k$.
  • `>> k` to szybkie dzielenie całkowite przez $2^k$.
  • Zawsze używaj nawiasów dla pewności: `(n & maska) == 0`.
  • W Pythonie `^` to XOR, a `**` to potęga.

Najczęściej Zadawane Pytania

Jaka jest różnica między `&` a `and`?

`&` to operator *bitowy*: `5 & 3` (`101 & 011`) daje `1`. `and` to operator *logiczny*: `5 and 3` daje `True` (w Pythonie zwraca `3`, ale w kontekście `if` liczy się jako `True`). `&` działa na bitach, `and` na wartościach logicznych.

Po co mi XOR? Jakie ma właściwości?

XOR ma dwie magiczne właściwości: 1) `x ^ x = 0` (XOR liczby z samą sobą daje zero). 2) `x ^ 0 = x` (XOR z zerem nie zmienia liczby). Jest też odwracalny: `(x ^ y) ^ y = x`. Używa się go w kryptografii, sumach kontrolnych i do 'przełączania' bitów.

Jak sprawdzić, czy liczba jest parzysta za pomocą bitów?

Liczba jest parzysta, jeśli jej ostatni bit (bit $2^0$) jest równy 0. Można to sprawdzić warunkiem `if (n & 1) == 0:`. Jeśli wynik to 0, jest parzysta. Jeśli 1, jest nieparzysta. To jest (marginalnie) szybsze niż `n % 2 == 0`.

Jak ustawić `k`-ty bit liczby `n` na 1?

Użyj operatora OR i maski. `n = n | (1 << k)`. To 'zapali' k-ty bit, nie ruszając pozostałych.

Jak wyzerować `k`-ty bit liczby `n`?

Użyj operatora AND i zanegowanej maski. `n = n & ~(1 << k)`. Maska `~(1 << k)` to liczba, która ma same jedynki, *oprócz* zera na `k`-tej pozycji. Operacja AND zachowa wszystkie bity `n` i wyzeruje ten jeden.

Chcesz opanować wszystkie tematy maturalne?

Dołącz do kursu i zyskaj dostęp do interaktywnych lekcji, edytora kodu i setek zadań.

Powiązane Tematy