Table of contents
Implement code functionality

How to generate random numbers in Python

May 22, 2025
 ・ by  
Claude and the Anthropic Team
Table of contents
H2 Link Template
Try Claude

Random number generation powers everything from cryptography to game development in Python. The language's built-in modules provide robust tools for creating both pseudo-random and true random numbers, with options for different probability distributions and ranges.

This guide covers essential techniques, practical applications, and troubleshooting tips for random number generation, featuring code examples created with Claude, an AI assistant built by Anthropic.

Basic random numbers with random.random()

import random
random_number = random.random()
print(random_number)
0.7237845954323937

The random.random() function generates a floating-point number between 0.0 and 1.0, following a uniform distribution where each value has an equal probability of being selected. This fundamental random number generator serves as a building block for creating random values in other ranges or distributions.

Python's random module uses the Mersenne Twister algorithm to produce these numbers. While not cryptographically secure, it provides sufficient randomness for most general applications like:

  • Simulating probability-based events
  • Generating test data
  • Creating random selections from datasets
  • Building simple games and animations

Basic random number techniques

Building on the basic random.random() function, Python's random module provides specialized methods for generating integers, floats within ranges, and random selections from sequences.

Generating integers with random.randint()

import random
random_integer = random.randint(1, 100)
print(random_integer)
42

The random.randint() function generates random integers within a specified inclusive range. Unlike random.random(), it returns whole numbers instead of decimals.

When calling random.randint(1, 100), Python selects a random integer between 1 and 100, including both endpoints. Each number has an equal probability of being chosen.

  • Both arguments must be integers
  • The first number must be less than or equal to the second
  • The function includes both boundary values in its selection pool

This makes randint() particularly useful for simulating dice rolls, generating random ages, or creating test data that requires whole numbers within specific bounds.

Creating random floats in a range with random.uniform()

import random
random_float = random.uniform(1.5, 8.5)
print(random_float)
5.273546789123456

The random.uniform() function generates floating-point numbers within a specified range, giving you precise control over the minimum and maximum values. Unlike random.random(), you can define any numerical boundaries you need.

  • The function takes two parameters: a minimum and maximum value
  • It returns a random float that includes the minimum but not the maximum value
  • Each possible float within the range has an equal probability of being selected

In the example, random.uniform(1.5, 8.5) produces a random decimal number between 1.5 and 8.5. This makes it ideal for simulating measurements, calculating prices, or generating test data that requires decimal precision.

Selecting random elements with random.choice()

import random
fruits = ["apple", "banana", "cherry", "date", "elderberry"]
random_fruit = random.choice(fruits)
print(random_fruit)
banana

The random.choice() function selects a single random element from any sequence like a list, tuple, or string. Each item has an equal probability of being chosen.

In the example, random.choice(fruits) randomly picks one fruit from the list and assigns it to random_fruit. The function handles all the complexity of generating random indices internally.

  • Works with any sequence type in Python
  • Returns exactly one element each time it's called
  • Raises an error if the sequence is empty

This makes random.choice() perfect for simulating random selections, creating game mechanics, or sampling data points from collections.

Advanced random number techniques

Building on these foundational techniques, Python offers powerful tools for generating large arrays of random numbers, working with statistical distributions, and creating reproducible results through seeding.

Generating arrays of random numbers with NumPy

import numpy as np
random_array = np.random.random(5)
print(random_array)
[0.12345678 0.23456789 0.34567891 0.45678912 0.56789123]

NumPy's random.random() function efficiently generates arrays of random floating-point numbers between 0 and 1. The integer argument specifies how many random numbers to create. In this case, np.random.random(5) produces an array containing exactly 5 random values.

  • NumPy arrays process data much faster than Python lists for large-scale random number generation
  • The generated numbers follow a uniform distribution, giving each value an equal probability
  • You can reshape these arrays into different dimensions for matrices or multi-dimensional data structures

This approach proves especially valuable when you need to generate thousands or millions of random numbers for simulations, data analysis, or machine learning applications. NumPy's optimized C backend handles the heavy lifting, making it significantly more efficient than using Python's built-in random module in a loop.

Creating random numbers with specific distributions

import numpy as np
normal_distribution = np.random.normal(0, 1, 5)
print(normal_distribution)
[-0.12345678  0.23456789 -1.34567891  0.45678912  1.56789123]

NumPy's random.normal() function generates random numbers that follow a normal (Gaussian) distribution. The function takes three key parameters: mean (center of the distribution), standard deviation (spread), and size (number of samples).

In the example, np.random.normal(0, 1, 5) creates 5 random numbers centered around 0 with a standard deviation of 1. This produces values that cluster around the mean, with decreasing probability as numbers get further from 0.

  • Values have a higher chance of being close to the mean (0)
  • About 68% of values fall within one standard deviation of the mean
  • The distribution creates a classic bell curve pattern

This type of distribution proves invaluable when modeling real-world phenomena like measurement errors, natural variations, or financial market movements that tend to follow normal patterns.

Setting seeds for reproducible random numbers

import random
import numpy as np
random.seed(42)
np.random.seed(42)
print(random.random())
print(np.random.random())
0.6394267984578837
0.37454011884736133

Setting a random seed ensures your random numbers follow the same sequence every time you run your code. The random.seed() and np.random.seed() functions initialize this sequence with a number of your choice.

  • Seeds make random operations reproducible. Running the same seed produces identical results across different executions
  • This reproducibility proves essential for debugging, testing, and scientific experiments
  • Both Python's random module and NumPy need separate seed initialization for consistent results

The example uses seed 42. Any value works, but 42 appears frequently in examples because of its cultural significance. Each subsequent call to random() or np.random.random() will generate the same "random" numbers in sequence.

Get unstuck faster with Claude

Claude is an AI assistant created by Anthropic that excels at helping developers write, debug, and understand code. It combines deep programming knowledge with natural conversation to provide clear, accurate guidance.

When you encounter tricky random number scenarios or need help optimizing your code, Claude can explain concepts, suggest improvements, and help you implement solutions. It can clarify the differences between random.randint() and random.randrange() or help you choose the right distribution for your data.

Start accelerating your Python development today. Sign up for free at Claude.ai to get personalized help with random number generation and other programming challenges.

Some real-world applications

Random number generation powers essential real-world applications that enhance security and solve complex mathematical problems through probability-based approaches.

Generating random passwords with random.choice()

The random.choice() function enables secure password generation by randomly selecting characters from custom character sets, allowing you to create strong passwords that meet specific complexity requirements.

import random
import string
characters = string.ascii_letters + string.digits + string.punctuation
password = ''.join(random.choice(characters) for _ in range(12))
print(password)

This code combines Python's built-in string and random modules to create a random string. The string.ascii_letters contains all letters (both cases), string.digits provides numbers 0-9, and string.punctuation adds special characters. These combine into a single string stored in characters.

The core functionality uses a generator expression with random.choice() to select 12 random characters from this pool. The join() method then combines these selections into the final string. This approach ensures the password includes a diverse mix of character types.

  • The underscore variable _ indicates we don't need the loop variable
  • The empty string '' serves as the separator between joined characters
  • Each run produces a unique 12-character string

Estimating π with Monte Carlo simulation

Monte Carlo simulation estimates the value of π by randomly plotting points inside a square containing a quarter circle, then calculating the ratio between points that fall inside versus outside the circle.

import random
import math

points = 10000
inside_circle = sum(1 for _ in range(points) if random.random()**2 + random.random()**2 <= 1)
pi_estimate = 4 * inside_circle / points
print(f"Estimated π: {pi_estimate}")
print(f"Math.pi: {math.pi}")

This code uses random number generation to approximate the mathematical constant π through a probability-based approach. The program generates 10,000 random points within a 1x1 square using random.random(). It then calculates how many points fall inside a quarter circle with radius 1 by checking if the squared coordinates sum to less than or equal to 1.

The ratio of points inside the circle to total points, multiplied by 4, gives us an estimate of π. This works because the ratio of the quarter circle's area to the square's area equals π/4. More points generally yield more accurate estimates.

  • The sum() function with a generator expression efficiently counts qualifying points
  • The **2 operator squares the random coordinates
  • The program compares the estimate to Python's built-in math.pi constant

Common errors and challenges

Python developers frequently encounter three critical random number generation pitfalls that can derail their code's reliability and functionality.

Forgetting to set a seed with random.seed() for reproducible results

When developers skip setting a random seed, their code produces different results with each execution. This makes debugging nearly impossible and creates inconsistent test outcomes. The random.seed() function solves this by initializing the random number generator to a known state.

import random

# Different results each time the script runs
result1 = random.randint(1, 100)
# If we run the script again, we can't reproduce the same numbers
print(f"Random number: {result1}")

Without a seed value, the random.randint() function generates unpredictable numbers that change with each program execution. This makes it impossible to replicate specific test cases or debug random number-dependent code. The solution appears in the code below.

import random

# Set seed for reproducibility
random.seed(42)
result1 = random.randint(1, 100)
# Same seed will produce the same sequence of random numbers
print(f"Reproducible random number: {result1}")

Setting random.seed(42) initializes the random number generator to a specific starting point. This ensures your code produces identical random numbers in the same sequence every time it runs. The seed value itself doesn't matter. What matters is using the same seed consistently throughout your testing and debugging process.

  • Always set seeds when writing unit tests that involve randomization
  • Use seeds during development to reproduce and fix bugs involving random numbers
  • Remember that different Python versions might produce different sequences even with the same seed

Watch for this issue when your code needs predictable results or when collaborating with other developers who need to replicate your random number sequences.

Confusion between random.randint() and random.randrange() boundaries

Developers often mix up the boundary behaviors of Python's random number functions. The key difference lies in their ranges: random.randint() includes both endpoints while random.randrange() excludes the upper bound. This distinction causes unexpected results when generating random integers.

import random
# Trying to get random number between 1 and 10
value1 = random.randint(1, 10)  # Includes 10
value2 = random.randrange(1, 10)  # Excludes 10
print(f"Values: {value1}, {value2}")

The code demonstrates how randint() and randrange() produce different outputs for seemingly identical ranges. This unexpected behavior can lead to off-by-one errors in your programs. Let's examine the corrected implementation below.

import random
# Getting random number between 1 and 10
value1 = random.randint(1, 10)  # Includes 10
value2 = random.randrange(1, 11)  # Now includes 10
print(f"Values: {value1}, {value2}")

To include the number 10 in the range when using random.randrange(), you must specify an upper bound of 11 instead of 10. This adjustment compensates for the function's exclusive upper boundary behavior. The corrected code demonstrates both approaches achieving the same outcome: random.randint(1, 10) and random.randrange(1, 11) will both generate numbers from 1 to 10 inclusive.

  • Always verify the boundary behavior when switching between these functions
  • Consider using randint() for simpler inclusive ranges
  • Watch for this issue when porting code between different random number generators

Error when using random.sample() with sample size larger than population

The random.sample() function generates unique random selections from a sequence. A common error occurs when developers request more items than exist in the source population. This raises a ValueError that can crash your program unexpectedly.

import random
fruits = ["apple", "banana", "cherry"]
# Trying to get 5 random fruits from a list of 3
random_fruits = random.sample(fruits, 5)
print(random_fruits)

The random.sample() function raises a ValueError because it can't select 5 unique items from a list containing only 3 fruits. The code below demonstrates the proper way to handle this limitation.

import random
fruits = ["apple", "banana", "cherry"]
# Sample safely with min() function
sample_size = min(5, len(fruits))
random_fruits = random.sample(fruits, sample_size)
print(random_fruits)

The min() function provides an elegant solution by dynamically adjusting the sample size to match the available items. This prevents the ValueError while still returning as many unique random selections as possible from the source sequence.

  • Always verify your sample size doesn't exceed the population size
  • Consider using error handling with try-except blocks for more complex scenarios
  • Watch for this issue when working with user-defined sample sizes or dynamic collections

This pattern proves especially useful in data processing applications where the size of input collections may vary. The solution maintains the random selection's integrity while gracefully handling edge cases.

Learning or leveling up? Use Claude

Claude combines advanced programming expertise with intuitive teaching abilities to guide you through Python's random number generation challenges. Its deep understanding of computer science principles and ability to explain complex concepts in simple terms makes it an invaluable companion for developers seeking to master randomization techniques.

Here are some example prompts to get started:

  • Debug random seed issues: Ask "Why do I get different random numbers each time I run my script?" and Claude will explain seed initialization for reproducible results
  • Distribution selection: Ask "Which random distribution should I use to simulate natural phenomena?" and Claude will help you choose between uniform, normal, and other statistical patterns
  • Performance optimization: Ask "How can I generate millions of random numbers efficiently?" and Claude will guide you through NumPy's optimized methods
  • Security considerations: Ask "Is random.random() secure enough for passwords?" and Claude will explain when to use cryptographic alternatives

Experience personalized coding assistance today by signing up at Claude.ai. The platform is free to use and requires no credit card.

For a more integrated development experience, Claude Code brings AI assistance directly into your terminal. This powerful tool helps you tackle complex random number generation challenges without leaving your development environment.

FAQs

Additional Resources

Troubleshoot software performance issues using Claude

2025-05-16
6 min
 read
Read more

How to use 'and' in Python

2025-05-30
14 min
 read
Read more

How to define a global variable in Python

2025-05-30
14 min
 read
Read more

Leading companies build with Claude

ReplitCognitionGithub CopilotCursorSourcegraph
Try Claude
Get API Access
Copy
Expand