Lekcja 1. Budowa komputera — od logiki bitów do współczesnych procesorów
ŚredniPo co się tego uczymy?
Kiedy piszesz program, raczej nie myślisz "a gdzie to się właściwie wykonuje w procesorze?" — ale komputer, który uruchamia Twój kod, ma bardzo konkretną, logiczną strukturę. Zrozumienie jej wyjaśnia, dlaczego program czasem działa wolno, jak system zarządza pamięcią i co naprawdę znaczy "optymalizacja" — to właśnie ta wiedza odróżnia kogoś, kto PISZE kod, od kogoś, kto ROZUMIE, jak kod pracuje.
Teoria
Architektura von Neumanna (John von Neumann, 1945) to podstawa WSZYSTKICH współczesnych urządzeń — od smartfonów po superkomputery. Cztery główne komponenty: Pamięć (przechowuje dane i program), CPU (odczytuje i wykonuje instrukcje), ALU — Arithmetic Logic Unit (wykonuje działania matematyczne i logiczne: +, −, ×, ÷, AND, OR, NOT), CU — Control Unit (steruje przepływem danych), I/O (komunikacja z otoczeniem: dysk, klawiatura, monitor). Przykład: gdy piszesz x = 5 + 3, procesor pobiera instrukcję z pamięci, ALU wykonuje dodawanie, a wynik (8) zapisywany jest z powrotem w pamięci.
Systemy liczbowe — bit, bajt i jednostki pochodne. Komputer przechowuje WSZYSTKIE dane binarnie (zerami i jedynkami). 1 bajt = 8 bitów (np. litera "A" = 01000001), 1 KB = 1024 bajty, 1 MB = 1024 KB, 1 GB = 1024 MB, 1 TB = 1024 GB.
Liczby ujemne — kod uzupełnieniowy do dwóch (Two's Complement) — standard w architekturach procesorów. Dla 8 bitów: +5 = 00000101, -5 = 11111011 (odwrócenie bitów i dodanie 1). Zakres liczb 8-bitowych: bez znaku 0-255, ze znakiem -128 do 127.
Liczby zmiennoprzecinkowe (IEEE 754) — do zapisu ułamków i bardzo dużych/małych liczb: 1 bit znak, 8 bitów wykładnik, 23 bity mantysa (dla 32 bitów). Klasyczny "błąd zaokrąglenia": 0.1 + 0.2 w Pythonie da 0.30000000000000004, nie 0.3 — dlatego przy obliczeniach zmiennoprzecinkowych trzeba UWAŻAĆ na dokładność.
Tekst i kodowanie (ASCII/Unicode) — każdy znak w pamięci to LICZBA: "A" = 65 (binarnie 01000001), "a" = 97, "0" = 48, spacja = 32. Unicode rozszerza ten system na cały świat — polskie litery, emoji, tysiące symboli.
Hierarchia pamięci — "złoty trójkąt" — im szybsza pamięć, tym droższa i mniejsza: Rejestry CPU (~64 bajty, nanosekundy) → Cache L1 (32 KB, ~4 ns) → Cache L2 (256 KB, ~10 ns) → Cache L3 (8 MB, ~40 ns) → RAM (8-32 GB, ~100 ns) → SSD (~10 000 ns) → HDD (~10 000 000 ns). Jeśli dostęp do rejestru trwałby 1 sekundę, dostęp do dysku HDD trwałby aż 116 DNI!
Procesor (CPU) składa się z: Jednostki Sterującej (CU — czyta i dekoduje instrukcje, kieruje operacjami) i Jednostki Arytmetyczno-Logicznej (ALU — wykonuje +, −, ×, ÷, AND, OR, porównania). Takt procesora (Clock Speed) to rytm impulsów zegara — 1 GHz = 1 miliard cykli na sekundę. Ale częstotliwość to nie wszystko — liczy się też liczba RDZENI i WĄTKÓW (np. i3: 2 rdzenie/4 wątki, i7: 8 rdzeni/16 wątków). Nowoczesne procesory łączą rdzenie wydajne (P-Cores) i efektywne (E-Cores), zintegrowaną grafikę (iGPU) i akceleratory AI.
Schemat
ARCHITEKTURA VON NEUMANNA:
┌─────────────┐
│ PAMIĘĆ │ ← przechowuje dane i program
└──────┬──────┘
│
┌───┴───────────────┬──────────────┐
│ │ │
┌──▼──┐ ┌──────▼────┐ ┌────▼───────┐
│ CPU │◄──────►│ ALU & CU │ │ REG. I/O │
└─────┘ └───────────┘ └────────────┘
HIERARCHIA PAMIĘCI (szybkość vs pojemność):
Rejestry CPU — ns (najszybsze, najmniejsze)
Cache L1/L2/L3 — ns-dziesiątki ns
RAM — ~100 ns
SSD — ~10 000 ns
HDD — ~10 000 000 ns (najwolniejsze, największe)
KOD U2 DLA -5 (8 bitów):
+5 = 00000101
-5 = 11111011 (odwrócenie bitów + dodanie 1)
Przykład z życia
Gdy komputer "zawiesza się" przy otwieraniu wielu dużych plików naraz, to często oznacza, że dane nie mieszczą się już w szybkiej pamięci RAM i system musi korzystać z dużo wolniejszego dysku (swap) — dokładnie ten sam mechanizm hierarchii pamięci, o którym mowa w tej lekcji, tłumaczy, dlaczego dokupienie RAM-u często realnie przyspiesza komputer bardziej niż szybszy procesor.
reprezentacja_danych.py
# Reprezentacja liczb ujemnych (kod U2) w Pythonie
x = 5
print(bin(x)) # 0b101
print(bin(-5)) # -0b101 (w pamięci procesora: 11111011)
# Błąd zaokrąglenia liczb zmiennoprzecinkowych (IEEE 754)
y = 0.1 + 0.2
print(y) # 0.30000000000000004 - NIE 0.3!
# Kodowanie znaków - ASCII i Unicode
print(ord('A')) # 65 (kod znaku 'A')
print(chr(65)) # 'A' (znak dla kodu 65)
print(ord('ą')) # 261 (polska litera w Unicode)
print(ord('😀')) # 128512 (emoji też ma swój kod!)
Komentarz i wyjaśnienie kodu
bin(-5) w Pythonie wypisuje -0b101 — Python POKAZUJE liczby ujemne z minusem dla wygody czytania, ale WEWNĄTRZ procesora faktyczna reprezentacja to kod U2 (11111011 dla 8 bitów) — to ważne rozróżnienie między tym, jak Python WYŚWIETLA liczbę, a jak faktycznie jest ona zakodowana w pamięci.
0.1 + 0.2 != 0.3 to NIE błąd Pythona — to fundamentalna własność reprezentacji liczb zmiennoprzecinkowych (IEEE 754) we WSZYSTKICH językach programowania: niektórych ułamków dziesiętnych nie da się DOKŁADNIE zapisać w systemie binarnym, podobnie jak 1/3 nie da się dokładnie zapisać w systemie dziesiętnym.
ord() i chr() to funkcje odwrotne do siebie — ord() zamienia ZNAK na jego liczbowy kod, chr() zamienia KOD z powrotem na znak. To pokazuje wprost, że "pod maską" każdy tekst to po prostu ciąg liczb.
Ćwiczenie samodzielne
Uruchom przykład i sprawdź ord() dla kilku innych znaków (małe/wielkie litery, cyfry, polskie znaki). Sprawdź też bin() dla kilku różnych liczb dodatnich i ujemnych.
Zadania do pracy własnej
Sprawdź w Pythonie kody ASCII/Unicode dla liter swojego imienia (funkcja
ord()) i zapisz wynik.Wyjaśnij własnymi słowami, dlaczego
0.1 + 0.2w Pythonie nie daje dokładnie0.3. Sprawdź, czy podobny problem występuje dla0.5 + 0.25.Oblicz "ręcznie" (na kartce) reprezentację liczby -12 w kodzie U2 na 8 bitach (zapisz +12 binarnie, odwróć bity, dodaj 1), a następnie zweryfikuj wynik funkcją
bin(-12)w Pythonie (pamiętaj, że Python pokazuje liczby ujemne inaczej niż surowa reprezentacja U2 — porównaj koncepcyjnie, nie dosłownie).
Typowe błędy
Mylenie sposobu WYŚWIETLANIA liczby ujemnej przez Pythona z jej rzeczywistą reprezentacją U2 w pamięci — bin(-5) pokazuje -0b101 dla czytelności, ale procesor faktycznie przechowuje ją jako 11111011 (dla 8 bitów).
Porównywanie liczb zmiennoprzecinkowych operatorem == bez uwzględnienia błędu zaokrąglenia — 0.1 + 0.2 == 0.3 zwróci False w większości języków programowania, mimo że matematycznie te wartości są równe.
Przekonanie, że "wyższy takt procesora" zawsze oznacza "szybszy komputer" — liczy się także liczba rdzeni/wątków oraz architektura; procesor o niższym takcie, ale z większą liczbą rdzeni, może być szybszy w zadaniach wielowątkowych.
Nawiązanie do egzaminu zawodowego
Ten temat to fundament teorii wymaganej w pisemnej części matury z informatyki oraz na egzaminach INF.03/INF.04 (systemy liczbowe, reprezentacja danych). W kolejnej lekcji zagłębisz się w systemy liczbowe (binarny, ósemkowy, szesnastkowy) dokładniej — z pełnymi metodami przeliczania między nimi.