random.gauss / normalvariate

Both give the same distribution with different algorithms, so the same seed gives different numbers. gauss() computes two values at a time and hands out the second on the next call; sigma is the standard deviation, not the variance.

random functionAll Python 3 versions (default arguments since 3.11)Live demo
Common call
random.gauss(170, 10)
Returns
float around mu (68% within one sigma)
Replaces
Hand-written Box-Muller code
Watch out
Can be negative or extreme; sigma is a standard deviation
random.gauss(mumu — The mean (center of the bell curve). Default since 3.11.type: float · default: 0.0=0.0, sigmasigma — The standard deviation (width). Default since 3.11. 0 returns mu every time.type: float · default: 1.0=1.0) / random.normalvariate(mu=0.0, sigmasigma — The standard deviation (width). Default since 3.11. 0 returns mu every time.type: float · default: 1.0=1.0)
→ float

Demo

Live evaluation
Five draws, rounded to 4 decimals. Most land within one sigma of mu.
Try:
Inputs
seedint | stran int or a string
mufloatmean
sigmafloatstandard deviation
Code
import random
random.seed(42)
[round(random.gauss(0.0, 1.0), 4) for _ in range(5)]
Result
[-0.1441, -0.1729, -0.1113, 0.702, -0.1276]

gauss() uses Box-Muller: two uniform floats give two normal values, cos(...) * r is returned and sin(...) * r is stored for the next call. That is why getstate()[2] after one call with seed 42 holds -0.172904: the second value of the gauss tab (shown there as -0.1729). normalvariate() (Kinderman-Monahan) draws pairs of uniforms in a loop and keeps nothing. The values are rounded because they come from the C math library, which can differ in the last digit between platforms.

Parameters

NameTypeRequiredDescription
mufloatno (0.0)The mean (center of the bell curve). Default since 3.11.
sigmafloatno (1.0)The standard deviation (width). Default since 3.11. 0 returns mu every time.

Return value

float — mu + z * sigma for a standard normal z; any real value is possible.

Common patterns

Simulated measurements
True value plus normally distributed noise.
import random
readings = [true_value + random.gauss(0, 0.5) for _ in range(100)]
Never negative
Clamp, or use lognormvariate for naturally positive quantities.
import random
duration = max(0.0, random.gauss(15.0, 3.5))
One generator per thread
Two threads sharing gauss() can receive the same cached value; separate Random instances avoid it.
import random
import threading
local = threading.local()
def rng():
    if not hasattr(local, "r"):
        local.r = random.Random()
    return local.r

Examples

1. Standard normal values
import random random.seed(42) [random.gauss(0, 1) for _ in range(3)]
Returns
[-0.14409032957792836, -0.1729036003315193, -0.11131586156766246]
2. normalvariate: same seed, other numbers
import random random.seed(42) [random.normalvariate(0, 1) for _ in range(3)]
Returns
[0.2453263417078634, -0.49684447341120286, 1.2547859310574627]
3. Heights in cm
import random random.seed(42) [round(random.gauss(170, 10), 1) for _ in range(5)]
Returns
[168.6, 168.3, 168.9, 177.0, 168.7]
4. Defaults mu=0.0, sigma=1.0 (3.11+)
import random random.seed(42) random.gauss()
Returns
-0.14409032957792836
5. The mean converges to mu
import random random.seed(42) data = [random.gauss(100, 15) for _ in range(10000)] round(sum(data) / len(data))
Returns
100
6. gauss() caches its second value
import random random.seed(42) random.gauss() state = random.getstate() state[2] is not None
Returns
True
7. seed() clears that cache
import random random.seed(42) first = random.gauss() random.seed(42) again = random.gauss() first == again
Returns
True

Pitfalls

1. Passing the variance as sigma
sigma is the standard deviation. If you want variance 4, pass sigma=2; gauss(0, 4) has standard deviation 4 (variance 16).
gauss(0, 4)
import random
import statistics
random.seed(42)
data = [random.gauss(0, 4) for _ in range(10000)]
round(statistics.stdev(data))
4
gauss(0, 2)
import random
import statistics
random.seed(42)
data = [random.gauss(0, 2) for _ in range(10000)]
round(statistics.stdev(data))
2
2. Negative values for positive quantities
A normal distribution has no lower bound: with mu=1 and sigma=2 about 31 percent of the draws are negative. Clamp or choose another distribution.
raw gauss
import random
random.seed(42)
min(random.gauss(1, 2) for _ in range(1000)) < 0
True
max(0.0, ...)
import random
random.seed(42)
min(max(0.0, random.gauss(1, 2)) for _ in range(1000))
0.0

When to use

Use it
  • Noise, measurement error, natural variation around a mean
  • Monte Carlo simulations needing normal inputs
  • normalvariate when several threads share one generator
Reach for something else
  • Bounded values → triangular, betavariate or clamping
  • Positive skewed quantities (incomes, durations) → lognormvariate, gammavariate
  • Arrays of millions of values → numpy.random.Generator.normal

Notes

CPython impl
Lib/random.py. gauss: x2pi = random() * TWOPI; g2rad = sqrt(-2.0 * log(1.0 - random())); returns cos(x2pi) * g2rad and stores sin(x2pi) * g2rad in self.gauss_next. normalvariate: Kinderman-Monahan ratio of uniforms, z = NV_MAGICCONST * (u1 - 0.5) / u2, accepted when z * z / 4.0 <= -log(u2)
Platforms
math.log, cos and sin come from the C library: in the reference fuzz (thousands of draws compared with Windows and Linux CPython) the last digit differs between platforms for a fraction of a percent of values. The demos therefore round to 4 or 6 decimals; the full-precision examples on this page were checked on both
Threads
Two threads calling gauss() at the same moment can get the same cached value; the docs suggest separate instances, locks, or normalvariate()

FAQ

Same normal distribution, different algorithms. gauss() (Box-Muller) produces two values per computation and caches one, so it is slightly faster but not safe for simultaneous calls from two threads; normalvariate() keeps no cache. For the same seed they return different numbers.