For numeric work, two standard library modules cover most everyday needs: math for general maths and statistics for basic stats.

For heavy data work you’ll switch to NumPy (Section 16) or SciPy. But for one-off calculations, these built-ins are perfect.

math — common functions and constants

import math

print(math.pi)            # 3.141592653589793
print(math.e)             # 2.718281828459045
print(math.inf)            # infinity
print(math.nan)            # not a number

print(math.sqrt(16))       # 4.0
print(math.pow(2, 10))     # 1024.0
print(math.exp(1))         # 2.718281828...   = e ** 1
print(math.log(math.e))    # 1.0              (natural log)
print(math.log10(1000))    # 3.0
print(math.log2(8))        # 3.0

For rounding and truncating:

print(math.floor(3.7))     # 3   round down
print(math.ceil(3.2))      # 4   round up
print(math.trunc(-3.7))    # -3  toward zero
print(round(3.5))          # 4   (round() is a built-in, not in math)

For absolute value:

print(abs(-7))             # 7   (built-in)
print(math.fabs(-7))       # 7.0 (math version — always float)

Trigonometry

Useful for graphics, physics, and signal processing:

import math

print(math.sin(0))                    # 0.0
print(math.cos(math.pi))              # -1.0
print(math.tan(math.pi / 4))          # 0.99... (≈ 1)

# convert between degrees and radians
print(math.radians(90))               # 1.5707...
print(math.degrees(math.pi))          # 180.0

All angle functions work in radians, not degrees. Use math.radians() and math.degrees() to convert when needed.

Useful tests

import math

print(math.isnan(float("nan")))      # True
print(math.isinf(float("inf")))      # True
print(math.isclose(0.1 + 0.2, 0.3))  # True — safe float comparison

math.isclose() is the right way to compare floats (we’ve mentioned this throughout the course):

# avoid
a == b

# prefer
math.isclose(a, b)
math.isclose(a, b, rel_tol=1e-9, abs_tol=0.0)   # tune the tolerance

Combinatorics — comb and perm

For counting:

print(math.comb(5, 2))     # 10 — "5 choose 2"
print(math.perm(5, 2))     # 20 — permutations
print(math.factorial(5))   # 120

Useful in probability problems and combinatorial setups.

statistics — basic stats

import statistics as stats

nums: list[float] = [10.0, 12.0, 23.0, 23.0, 16.0, 23.0, 21.0, 16.0]

print(stats.mean(nums))           # 18.0   (average)
print(stats.median(nums))         # 18.5
print(stats.mode(nums))           # 23.0   (most common)
print(stats.stdev(nums))          # 5.24...  (sample standard deviation)
print(stats.variance(nums))       # 27.43... (sample variance)

For population (rather than sample) stats:

print(stats.pstdev(nums))         # population standard deviation
print(stats.pvariance(nums))      # population variance

The difference: sample versions divide by n - 1; population versions divide by n. For a list that represents the entire population, use pstdev. For a sample of a larger population, use stdev.

Quantiles

For percentiles and quartiles:

print(stats.quantiles(nums, n=4))      # [13.0, 18.5, 23.0]  — quartiles
print(stats.quantiles(nums, n=10))     # deciles

n=4 gives the three values that split the data into 4 equal parts. n=10 gives deciles, n=100 gives percentiles.

NormalDist — quick statistical modelling

nd = stats.NormalDist(mu=170, sigma=10)   # mean 170, std 10
print(nd.cdf(180))           # 0.84...  — probability X <= 180
print(nd.inv_cdf(0.5))       # 170      — value where probability is 50%
print(nd.samples(5))         # 5 random samples from the distribution

Useful for back-of-envelope statistical reasoning when you don’t want to pull in scipy.stats.

A practical example

Compare two sets of test scores:

import statistics as stats

before: list[float] = [62, 71, 65, 70, 68, 64, 69, 66]
after:  list[float] = [78, 82, 75, 88, 80, 79, 84, 81]

improvement: float = stats.mean(after) - stats.mean(before)
print(f"Mean improvement: {improvement:.1f}")
print(f"Stdev before: {stats.stdev(before):.2f}")
print(f"Stdev after:  {stats.stdev(after):.2f}")

For real hypothesis testing you’d use scipy.stats, but for quick reporting, statistics is plenty.

When to upgrade to NumPy

The standard library is fine for scalars and small lists. The moment you have:

  • More than a few thousand numbers
  • Multi-dimensional data (matrices, tensors)
  • Element-wise operations across arrays
  • Random sampling at scale

…switch to NumPy. It’s 10–100× faster and has a much richer API. We’ll cover the basics in Section 16.

What’s next

Numbers handled. Next, random — random numbers, shuffling, and sampling.

Toggle theme (T)