math, random & statistics
Three standard-library modules cover most everyday numeric needs: math for rounding, roots, logarithms and trigonometry; random for simulations, games and sampling; and statistics for averages and spread. (For security-sensitive randomness, there's secrets.)
The math module
import math print(math.floor(4.7), math.ceil(4.2), math.trunc(-4.7)) print(math.sqrt(144), math.isqrt(150), math.cbrt(27)) print(math.pow(2, 10), 2 ** 10) print(math.factorial(6), math.comb(5, 2), math.perm(5, 2)) print(math.gcd(48, 18), math.lcm(4, 6)) print(math.prod([1, 2, 3, 4]), math.fsum([0.1] * 10))
4 5 -4 12.0 12 3.0 1024.0 1024 720 10 20 6 12 24 1.0
floorrounds down,ceilrounds up,truncdrops the decimal part (towards zero).isqrtis the exact integer square root;combandpermcount combinations and permutations.fsumadds floats more accurately thansum—sum([0.1] * 10)gives0.9999999999999999.
Constants, logs and trigonometry
import math print(round(math.pi, 5), round(math.e, 5), math.inf > 1e308) print(math.log(math.e), math.log10(1000), math.log2(1024), math.log(8, 2)) angle = math.radians(30) print(round(math.sin(angle), 3), round(math.degrees(math.atan2(1, 1)), 1)) print(math.hypot(3, 4), math.dist((0, 0), (6, 8))) print(math.isclose(0.1 + 0.2, 0.3), math.isnan(float("nan")))
3.14159 2.71828 True 1.0 3.0 10.0 3.0 0.5 45.0 5.0 10.0 True True
Trigonometric functions work in radians — convert with radians() and degrees(). Always compare floats with isclose(), not ==.
Random numbers
import random random.seed(42) print(random.random()) print(random.randint(1, 6)) print(random.uniform(1.5, 2.5)) print(random.randrange(0, 100, 10)) print(random.choice(["rock", "paper", "scissors"]))
0.6394267984578837 1 2.241550499759833 30 rock
| Function | Returns |
|---|---|
random() | Float in [0.0, 1.0) |
randint(a, b) | Integer from a to b, both included |
uniform(a, b) | Float between a and b |
randrange(start, stop, step) | Like range, but one random value |
choice(seq) | One random item |
random.seed(42) makes the sequence repeatable — the same seed always produces the same "random" numbers, which is invaluable for tests and reproducible simulations.
Shuffling and sampling
import random random.seed(7) deck = list(range(1, 11)) random.shuffle(deck) print(deck) print(random.sample(range(1, 50), 6)) print(random.choices(["win", "lose"], weights=[1, 9], k=10).count("win") <= 10)
[9, 4, 2, 5, 8, 1, 10, 7, 3, 6] [33, 14, 3, 6, 28, 27] True
shufflereorders a list in place.sample(population, k)pickskdifferent items (like drawing lottery numbers).choices(population, weights, k)pickskitems with replacement, optionally weighted.
A quick simulation
import random random.seed(2026) trials = 100_000 sixes = sum(1 for _ in range(trials) if random.randint(1, 6) == 6) print(f"Rolled a six {sixes / trials:.1%} of the time (expected 16.7%)")
Rolled a six 16.5% of the time (expected 16.7%)
secrets: randomness for security
The random module is predictable by design and must never be used for passwords, tokens or anything security-related. Use secrets instead:
import secrets import string token = secrets.token_urlsafe(16) alphabet = string.ascii_letters + string.digits password = "".join(secrets.choice(alphabet) for _ in range(12)) print(len(token) > 16, len(password))
True 12
The statistics module
import statistics as st scores = [72, 88, 95, 61, 88, 79, 84] print(st.mean(scores), st.median(scores), st.mode(scores)) print(round(st.stdev(scores), 2), round(st.pstdev(scores), 2)) print(st.quantiles(scores, n=4)) print(round(st.correlation([1, 2, 3, 4], [2, 4, 5, 9]), 3))
81 84 88 11.46 10.61 [72.0, 84.0, 88.0] 0.965
stdev is the sample standard deviation and pstdev the population version. For heavier number-crunching on large arrays, NumPy is much faster — see the NumPy course.