When studying the behavior of a program or model, it’s often necessary to work with different ranges of values. Python comes to the rescue with its “random” module, allowing us to effortlessly generate random numbers.

In this blog, we’ll delve into the exciting world of random number generation in Python. We’ll start by learning how to generate a single random number and then expand our knowledge to create lists of random numbers.

## syntax of the random module

The `random`

module in Python allows you to generate random numbers, select random elements from a list, and perform other random-related operations.

To begin, you need to import the `random`

module at the beginning of your Python script or program:

`import random`

Once imported, you can use various functions provided by the `random`

module.

Here are a few commonly used:

1. `random.random()`

: Generates a random float number between 0 and 1.

Example:

x = random.random()

2. `random.randint(a, b)`

: Generates a random integer between `a`

and `b`

, inclusive.

Example:

x = random.randint(1, 10)

3. `random.choice(sequence)`

: Returns a random element from a sequence (list, tuple, or string).

Example:

```
my_list = [1, 2, 3, 4, 5]
x = random.choice(my_list)
```

4. `random.shuffle(sequence)`

: Shuffles the elements in a sequence randomly. Example:

my_list = [1, 2, 3, 4, 5] random.shuffle(my_list)

## Generating random integers

If you want to generate random whole numbers (integers) in Python, you can use the `random`

module. This module helps you do random things, like picking random numbers or items.

```
import random
# Generate a random integer between 0 and 9
random_int = random.randint(0, 9)
print(random_int)
# Generate a random integer between 1 and 100
random_int2 = random.randint(1, 100)
print(random_int2)
```

Output: The output will be random every time

```
3
86
```

In this example, the `random.randint(a, b)`

function is used to generate a random integer between `a`

and `b`

, inclusive. The generated integer is then stored in the `random_int`

and `random_int2`

variables.

You can adjust the range (`a`

and `b`

values) based on your requirements. The generated random integers will be different each time you run the code.

## Generating Random Numbers within a Range

To generate random numbers within a range, you can use the `random.randint(a, b)`

function. The `a`

and `b`

values represent the range within which you want the random number to be generated.

For example, if you want a random number between 1 and 100, you can use `random.randint(1, 100)`

. This function will give you a random whole number between 1 and 100, including both 1 and 100.

example:

```
import random
random_number = random.randint(1, 100)
print(random_number)
```

Output:

`25`

When you run this code, it will display a random number between 1 and 100. Each time you run the code, you’ll get a different random number within that range.

You can adjust the `a`

and `b`

values in `random.randint(a, b)`

to generate random numbers within different ranges.

## Generating random floating point numbers

To generate random floating-point numbers, you can use the `random.random()`

function. This function generates a random decimal number between 0 and 1.

Example:

```
import random
random_float = random.random()
print(random_float)
```

Output:

When you run this code, it will display a random decimal number between 0 and 1. Each time you run the code, you’ll get a different random number within that range.

`0.6275035897557025`

If you want to generate random floating-point numbers within a specific range, you can multiply the result of `random.random()`

by the desired range and add the minimum value. For example, to generate a random float between 10 and 20:

import random random_float = random.random() * (20 - 10) + 10 print(random_float)

Output:

In this case, `random.random()`

generates a number between 0 and 1, which is then multiplied by the range (10 in this case) and added to the minimum value (10 in this case).

`17.5983576683903`

## Seeding the random number generator

Seeding the random number generator allows you to generate the same sequence of random numbers. It can be useful when you want to reproduce a specific set of random numbers or if you need predictable randomness.

To seed the random number generator in Python, you can use the `random.seed()`

function. The seed is an initial value that determines the sequence of random numbers generated.

Example:

```
import random
random.seed(42) # Seed the random number generator
random_number = random.randint(1, 10)
print(random_number)
```

Output:

In this example, `random.seed(42)`

seeds the random number generator with the value `42`

. This means that every time you run the code, it will generate the same sequence of random numbers.

`2`

If you want different sequences of random numbers, you can use different seed values.

For example:

import random random.seed(1234) # Seed 1 random_number1 = random.randint(1, 10) random.seed(5678) # Seed 2 random_number2 = random.randint(1, 10) print(random_number1, random_number2)

Output:

In this case, `random_number1`

and `random_number2`

will be different because we seeded the random number generator with different values.

By not providing a specific seed value (i.e., not calling `random.seed()`

), the random number generator is seeded based on the current system time, ensuring a different sequence of random numbers each time the code is run.

`8 4`

## Handling Random Numbers in Multithreaded Environments

```
import random
import threading
# Each thread generates its own random numbers
def generate_random_numbers():
my_random = random.Random() # Create a separate random number generator for each thread
thread_id = threading.get_ident() # Get the ID of the current thread
# Generate and print 5 random numbers
for _ in range(5):
random_number = my_random.randint(1, 100)
print(f"Thread ID {thread_id} generated: {random_number}")
# Create multiple threads
threads = []
for _ in range(3):
thread = threading.Thread(target=generate_random_numbers)
threads.append(thread)
# Start the threads
for thread in threads:
thread.start()
# Wait for all threads to finish
for thread in threads:
thread.join()
```

In this example, we have a program with multiple threads. Each thread generates its own set of random numbers. The `generate_random_numbers()`

function is called by each thread, and it generates and prints 5 random numbers using its own random number generator.

We create three threads and start them. Each thread generates its own sequence of random number, and the output will show the thread ID and the generated random numbers.

Output:

```
Thread ID 123: 42
Thread ID 456: 78
Thread ID 789: 15
Thread ID 123: 90
Thread ID 789: 27
Thread ID 456: 59
Thread ID 789: 32
Thread ID 123: 11
Thread ID 456: 87
Thread ID 789: 52
Thread ID 123: 19
Thread ID 456: 91
```

## Example: Lotteries and Gambling

```
import random
def run_lottery():
participants = ['Aman', 'Monu', 'Rajesh', 'Priya', 'Neha']
winner = random.choice(participants)
print(f"The winner of the lottery is: {winner}!")
run_lottery()
```

Output:

In this example, the `participants`

list now includes Indian names such as ‘Aman’, ‘Monu’, ‘Rajesh’, ‘Priya’, and ‘Neha’. The `random.choice(participants)`

function is still used to select a winner randomly from the list.

When you run the code, it will randomly choose a winner from the Indian names provided in the participant’s list and display their name as the result of the lottery.

`The winner of the lottery is: Aman!`

## Example: Cryptography and Encryption

```
import random
def generate_encryption_key(key_length):
key = bytearray()
for _ in range(key_length):
random_byte = random.randint(0, 255)
key.append(random_byte)
return bytes(key)
# Example usage
encryption_key = generate_encryption_key(16) # Generate a 16-byte (128-bit) encryption key
print(f"Generated Encryption Key: {encryption_key.hex()}")
```

Output:

In this code, the `generate_encryption_key()`

function uses the `random.randint(a, b)`

function from the `random`

module to generate random integers between 0 and 255. It repeatedly generates random bytes and appends them to a byte array to form the encryption key.

`Generated Encryption Key: 588d78ec53cd7af870e5612cd09706af`

However, please note that using `random`

for cryptographic purposes is not recommended due to the predictable nature and statistical biases of the `random`

module. For secure encryption keys, it’s best to use a cryptographically secure random number generator like `os.urandom()`

or other specialized libraries.

## Statistical Analysis and Sampling

```
import random
def perform_random_sampling(population, sample_size):
sample = random.sample(population, sample_size)
return sample
# Example usage
population = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']
sample_size = 5
random_sample = perform_random_sampling(population, sample_size)
print(f"Random Sample: {random_sample}")
```

Output:

In this code, the `random.sample(population, sample_size)`

function is used to perform random sampling from the `population`

list. It returns a new list (`sample`

) containing `sample_size`

number of elements randomly chosen from the population without replacement.

The `perform_random_sampling()`

function takes the population list and the desired sample size as inputs, and it returns the random sample.

When you run the code, it will randomly select a sample of the specified size from the population and display the random sample.

`Random Sample: ['H', 'E', 'I', 'A', 'C']`

The random sample generated ensures unbiased results and represents a subset of the population for statistical analysis, experimentation, or simulations.

Image Credit: Photo by Mati Mango