Pythonmath & random Modules

math & random Modules

Python's numeric type system covers the basic arithmetic operators, but anything beyond +, -, *, / usually means reaching for the math module — square roots, rounding, trigonometry, logarithms, and mathematical constants. Alongside it, the random module provides tools for generating pseudo-random numbers, which are essential for simulations, games, sampling, and shuffling data. Both are part of the standard library, so no installation is required.

The `math` Module

math works exclusively with int/float numbers (not complex numbers — that's what the separate cmath module is for) and exposes both functions and constants.

Python
import math

print(math.sqrt(64))
print(math.floor(4.7))
print(math.ceil(4.2))
print(math.pi)
print(math.pow(2, 10))
print(2 ** 10)
8.0
4
5
3.141592653589793
1024.0
1024

Notice that math.pow() always returns a float, even for whole-number results, while the built-in ** operator returns an int when given two integers. For everyday exponentiation, ** is usually simpler and preferred; math.pow() exists mainly for consistency with other math functions and for cases where you specifically want a float back.

Trigonometry and Logarithms

math also includes the standard trigonometric functions, which work in radians, not degrees — use math.radians() to convert a degree value first.

Python
import math

angle_degrees = 90
angle_radians = math.radians(angle_degrees)

print(angle_radians)
print(math.sin(angle_radians))
print(math.cos(math.radians(0)))
print(math.log(math.e))
print(math.log(100, 10))
1.5707963267948966
1.0
1.0
1.0
2.0

math.log(x) computes the natural logarithm (base e) by default; passing a second argument computes the logarithm in that base instead.

Common `math` Functions at a Glance

Function / constant

Purpose

math.sqrt(x)

Square root

math.floor(x) / math.ceil(x)

Round down / up to nearest integer

math.pow(x, y)

x raised to the power y, always returns a float

math.pi / math.e

The constants π and e

math.sin, math.cos, math.tan

Trigonometric functions (radians)

math.radians(deg)

Convert degrees to radians

math.log(x, base=e)

Logarithm, natural by default

The `random` Module

random generates pseudo-random values — numbers that look statistically random but are actually produced by a deterministic algorithm seeded from some starting state (by default, something like the system clock).

Python
import random

print(random.random())            # float in [0.0, 1.0)
print(random.randint(1, 6))       # int in [1, 6], both ends inclusive
print(random.choice(["rock", "paper", "scissors"]))

deck = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
random.shuffle(deck)              # shuffles in place, returns None
print(deck)

hand = random.sample(deck, 3)     # pick 3 unique items without replacement
print(hand)
0.7304598921453987
4
paper
[7, 2, 9, 4, 1, 10, 6, 3, 8, 5]
[9, 6, 1]

A few distinctions worth remembering: random.shuffle() mutates the list in place and returns None (a common source of bugs when someone writes deck = random.shuffle(deck)), while random.sample() returns a new list and leaves the original untouched. random.choice() picks one element and can pick the same element again on a later call; random.sample() never repeats an element within a single call.

Common `random` Functions at a Glance

Function

Returns

random.random()

Float between 0.0 (inclusive) and 1.0 (exclusive)

random.randint(a, b)

Integer between a and b, both inclusive

random.choice(seq)

One random element from a sequence

random.shuffle(list)

Shuffles the list in place; returns None

random.sample(population, k)

A new list of k unique elements, no repeats

Warning
The `random` module is **not** cryptographically secure. Its output is predictable enough to be reconstructed by an attacker who knows or guesses the internal state, so never use it to generate passwords, tokens, API keys, or anything security-sensitive. For that, use the `secrets` module instead, which is specifically designed for cryptographic use:

Python
import secrets

token = secrets.token_hex(16)
print(token)
e4f3a1c9b02d7e6f1a4c8b3d5f0a9e7c
Seeding for Reproducible Randomness

By default, each run of a program produces a different sequence of "random" values. Calling random.seed(value) resets the internal state to a known point, so the exact same sequence of calls will always produce the exact same results. This is extremely useful for writing reproducible tests, debugging simulations, or sharing an exact scenario with someone else.

Python
import random

random.seed(42)
print([random.randint(1, 100) for _ in range(5)])

random.seed(42)
print([random.randint(1, 100) for _ in range(5)])

random.seed(7)
print([random.randint(1, 100) for _ in range(5)])
[82, 15, 4, 95, 36]
[82, 15, 4, 95, 36]
[51, 80, 27, 44, 69]

The first two calls use the same seed (42) and produce identical sequences, while the third call with seed 7 produces a completely different — but equally reproducible — sequence.

Tip
Seeding is a great fit for unit tests that involve randomness: seed at the start of the test so assertions on the "random" output are stable across runs.
Note
Never rely on `random.seed()` for security purposes — a fixed seed makes output *more* predictable, which is the opposite of what you want for tokens or passwords. Seeding is a tool for reproducibility, not security.
Quick Reference
  • math works with real numbers only; angles for trig functions are in radians.

  • ** is generally preferred over math.pow() for simple exponentiation.

  • random.random(), randint(), choice(), shuffle(), and sample() cover most everyday randomness needs.

  • Use secrets, not random, for anything security-sensitive.

  • random.seed() makes a sequence of random calls reproducible — useful for tests and simulations.