Lekcja 3: Losowość i liczenie
Zbuduj w Pythonie wzór „Deska Galtona” i po drodze naucz się:
- liczby losowe z np.random.default_rng
- True i False liczone jako 1 i 0
- liczenie przez np.bincount
- wyrażenie listowe
- symulacja sprawdzona wzorem
Najpierw obejrzyj
Film gra z YouTube po kliknięciu.
"""Galton board: every ball goes left or right at random at each of 12 rows of pegs.
Run: python galton-board.py (needs: pip install numpy matplotlib)
"""
from math import comb
import numpy as np
import matplotlib.pyplot as plt
plt.style.use("dark_background")
rows, balls, p = 12, 5000, 0.5 # p: the chance of bouncing right
rng = np.random.default_rng()
bins = (rng.random((balls, rows)) < p).sum(axis=1) # a ball's bin = how often it went right
counts = np.bincount(bins, minlength=rows + 1)
k = np.arange(rows + 1)
expected = [balls * comb(rows, i) * p**i * (1 - p) ** (rows - i) for i in k] # the binomial curve
plt.figure(figsize=(7, 4))
plt.bar(k, counts, color="#5eead4", label="balls")
plt.xlabel("bin = times the ball went right")
plt.plot(k, expected, color="white", label="C(n, k) p^k (1-p)^(n-k)")
plt.legend()
plt.show()
# Try: p = 0.65 tilts the board; rows = 24 makes the bell narrower for its width
Nie masz Pythona na tym komputerze? Notatnik uruchamia ten sam skrypt, zadania i odpowiedzi w przeglądarce, w Google Colab. Notatnik jest po angielsku.
Linijka po linijce
rng = np.random.default_rng()Generator liczb losowych numpy. Daj mu liczbę, default_rng(1), a każde uruchomienie da te same „losowe” liczby.
bins = (rng.random((balls, rows)) < p).sum(axis=1)Tablica 5000 × 12 liczb losowych od 0 do 1. Każda mniejsza od p to True, czyli odbicie w prawo; suma wiersza liczy jego wartości True, a to jest przegródka kulki.
counts = np.bincount(bins, minlength=rows + 1)Ile kulek wpadło do każdej przegródki od 0 do 12; minlength pilnuje, żeby puste przegródki na brzegach liczyły się jako 0.
expected = [balls * comb(rows, i) * p**i * (1 - p) ** (rows - i) for i in k]Wyrażenie listowe: wzór dwumianowy dla każdej przegródki i, razy liczba kulek.
plt.bar(k, counts, color="#5eead4", label="balls")Jeden słupek na przegródkę. Biała linia narysowana potem to wzór, do porównania.
Twoja kolej
Uruchom skrypt dwa razy. Czy słupki są takie same? Potem spraw, żeby każde uruchomienie było takie samo.
Podpowiedź
Daj default_rng liczbę.
Odpowiedź
Słupki za każdym razem trochę się różnią. rng = np.random.default_rng(1) daje za każdym razem ten sam przebieg.
Ile z 5000 kulek powinno wpaść do środkowej przegródki przy 12 rzędach?
Podpowiedź
Udział środkowej przegródki to comb(12, 6) / 2**12.
Odpowiedź
5000 × 924 ÷ 4096 ≈ 1128.
Przechyl deskę: p = 0.65. Gdzie jest teraz środek dzwonu?
Podpowiedź
Środek to rows · p.
Odpowiedź
12 × 0,65 = 7,8, więc szczyt przesuwa się do przegródek 7 i 8.
Quiz
Fiszki
Przeczytaj przód, powiedz sobie, co jest z tyłu, potem otwórz kartę.
np.random.default_rng(seed)
Generator liczb losowych; to samo ziarno daje te same liczby.
array < 0.5
Tablica True i False; przy dodawaniu True liczy się jako 1.
np.bincount(xs)
Ile razy każda liczba całkowita 0, 1, 2, … występuje w xs.
[f(i) for i in k]
Wyrażenie listowe: nowa lista z f zastosowaną do każdego elementu k.
comb(n, k)
Liczba sposobów wyboru k rzeczy z n: math.comb(12, 6) to 924.