Python

# Generate random numbers in Python

There are two types of random number generators: pseudo-random number generator and true random number generator.
Pseudorandom numbers depend on computer algorithms. The computer uses algorithms to generate random numbers. These random numbers are not truly random because they are predictable like the generated numbers using NumPy random seed.

Whereas, truly random numbers are generated by measuring truly physical random parameters so we can ensure that the generated numbers are truly random.

The pseudo-random numbers are not safe to use in cryptography because they can be guessed by attackers.

In Python, the built-in random module generates pseudo-random numbers. In this tutorial, we will discuss both types. So let’s get started.

## Random number between 0 and 100

To generate one random number between a range for example 0 to 100, we can use the randint() method of the random module. The syntax for randint() is as follows:

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

It will return an integer n between a and b. Note that a and b are included in the output. Meaning that the random number can be a or b or any number between a and b.

Code:

```import random
print(random.randint(0, 100))
```

Output: As seen in the above example, you need to import the random module first. Then call randint(). This method will give you a random integer.

## Random number with a step size

Another function to generate an integer random number within a specified range is randrange(). The randrange() method can take up to three arguments that are: start, stop and step. The syntax of randrange() is given below:

Syntax:

```random.randrange(start, stop, step)
```

The return integer is between start (including start) and ends at stop (stop not included). The step specifies the increment value to find the random number and it defaults to 1.

For example, if start equals 0, stop equals 15 and step is 3, then the random number will be the multiple of 3 that is: 0, 3, 6, 9, 12, or 15.

In other words, the step is the increment value that is added to the starting value.
Note that the start and step arguments in the function are optional.

Code:

```import random
random.randrange(0, 15, 3)
```

Output: The difference between the randrange() and randint() is that the stop value is not included in the randrange() method and is included in the randint() method.

## Random floating/double number in a range

The random module provides several functions to generate a floating number in the given range.
The method uniform(a, b) can generate a number n between a and b.

It will return a floating number n between a and b. Note that a and b are included in the output. Meaning that the random number can be a or b or any number between a and b.

Code:

```import random
random.uniform(0, 10)
```

Output: Another method to generate a floating random number is by using the random() function.

The syntax for random() function is as follows:

```random.random()
```

The random() function does not take any arguments. It will generate a floating-point random number between the range 0 and 1 where 1 is not included in the output. The range is defined as: [0.0, 1.0).

Code:

```import random
random.random()
```

Output: ## Random number from Iterable

To generate a random number from an iterable (stack or sequence), Python random module has a function called random.choice(seq).
The random.choice(seq) method will return a random element from the given sequence.

### Using random.choice()

Code:

```import random
x = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
random.choice(x)
```

Output: You can also use randint() and randrange() functions to pick a random element from a given sequence.

### Using randint()

Code:

```import random
x = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
index = random.randint(0, len(x)-1)
x[index]
```

Output: In this code, we have created a list first, then picked a random integer from 0 to the length of the list. Then using indexing, we found the letter in the random index from the list.

This way we can get a random element from the list using randint().

### Using randrange()

Code:

```import random
x = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
index = random.randrange(0, len(x))
x[index]

```

Output: Notice that we subtracted 1 from the length of the list in the randint() method and subtracted nothing in the randrange() method. This is because the randint() includes the stop point. Therefore, we had to subtract 1.

## Excluding certain numbers from a range (Conditional choice)

To generate random numbers in a given range excluding some numbers we can use the random.choice() method. Consider the example below:

Code:

```import random
print (random.choice([x for x in range(0, 10) if x not in [1, 3, 5, 7, 9]]))
```

Output: In this example, we have used the for loop to iterate through a list of elements from 0 to 10.

Then we used a condition that the iterative (x) in range (0, 10) should not be present in the given list of odd numbers. Therefore, the generated number will always be an even number.

## Random number of length N

In Python, you can generate a random number with a fixed length that is n number of digits in the number. For instance, you want to generate a random number of length n where n = 3.

The three-digit random number can be generated within the range of 100 to 999. Therefore, in the randint() method, specify the starting point to be 100 and the ending point to be 999.

In the randint() method, starting and ending points are included.
Consider the example below:

Code:

```import random
print (random.randint(100, 999))
```

Output: ## Random numbers in a two-dimensional array

In Python, you can create an array or a two-dimensional array filled with random numbers by using the random() method with the range() function.

The range() function generates a sequence of numbers within the given range.
To generate an array of random numbers, we will generate a sequence of numbers within the given range first, then we will pick random numbers from the range and store them in an array as demonstrated in the code below:

Code:

```import random
[random.random() for i in range(0,5)]
```

Output: Similarly, to create a two-dimensional array, you can use nested list comprehension. List comprehension is a short way to create lists in Python as shown below:

Code:

```[[random.random() for i in range(0, 3)] for j in range(0, 3)]
```

Output: The newly created two-dimensional array contains 3 rows and 3 columns.

## Random number probability

Consider we are given a list of elements and we have to pick random elements from the list according to their priority.

What we will do is assign weights to the elements of the list. The element with the highest weight will have more chance to appear in the resultant list.

In other words, the element with the highest weight will have the highest probability to be added to the new list.
In Python, we can pick a random element from a list based on its probability by using the choices() method of the random module. The syntax for choices() method is as follows:

Syntax:

```random.choices(sequence, weights, cum_weights, k)
```
• sequence: is an iterable of Python such as a list, tuple, or a range of numbers.
• weights: is optional. It is a list to specify the relative weights of the elements in the given sequence. The weights specify the probability or possibility for an element to be selected.
• cum_weights is optional. It is a list to specify the cumulative weights of the elements in the given sequence. The weights specify the probability or possibility for an element to be selected.
• k is optional. It is an integer defining the size (length) of the resultant list.

The relative weight is calculated using the following formula:

```relative_weight = weight of element / sum of all weights
```

Whereas, the cumulative weight of an element is calculated using the following formula:

`cumulative_weight = weight of previous element + weight of the current element`

The return type of random.choices() is a k sized list of the elements picked based on the weights of the elements of the input list.
The use of the choices() method is demonstrated in the code below:

Code:

```import random
input_list = ['school', 'book', 'bag', 'bottle']
output_list = random.choices(input_list, weights = [10, 30, 40, 20], k = 8)
print(output_list)
```

Output: It can be seen in the output that the element ‘bag’ has the highest probability, therefore, it has the highest probability to reoccur in the resultant list.

## Mean and standard deviation

The random module provides methods to generate random numbers with a given mean and a standard deviation.
To generate a random number in a normal distribution, the method called random.normalvariate() is used. The syntax for the normalvariate() method is as follows:

Syntax:

`random.normalvariate(mu, sigma)`
• mu is the mean
• sigma is the standard deviation

The random.normalvariate(mu, sigma) returns a floating-point random number with normal distribution.
Similarly, we have methods to generate random numbers with Gaussian distribution and log normal distribution.

The random.gauss(mu, sigma) is used to generate a floating-point random number with the gaussian distribution. The random.lognormvariate(mu, sigma) generates a floating-point random number with the log normal distribution.

Code:

```import random
random.normalvariate(2, 6)
random.gauss(2, 6)
random.lognormvariate(2, 6)
```

Output: In the following example, we will generate a range of random numbers and plot a graph using matplotlib to observe the above-mentioned distributions.

Code:

```import random
import matplotlib.pyplot as plt
normal_dist = [random.normalvariate(250, 100) for i in range(100)]
plt.plot(normal_dist)
plt.show()

```

Output: With Gaussian distribution, the code and graph will be:

Code:

```gauss_dist = [random.gauss(250, 100) for i in range(100)]
plt.plot(gauss_dist)
plt.show()

```

Output: Similarly, with log normal distribution, the code and graph will be:

Code:

```lognormvariate_list = [random.lognormvariate(250, 100) for i in range(100)]
plt.plot(lognormvariate_list)
plt.show()
```

Output: ## Negative random number

The mid-point of the number line in mathematics is 0. The numbers to the right of 0 are positive real numbers and the number to the left side of 0 are negative real numbers.
To generate a negative random number, you can specify the range starting from a negative number and stopping at 0. Consider the example below:

Code:

```import random
random.uniform(-10, 0)
random.randrange(-50, 0)
random.randint(-40, 0)
```

Output: In the above example, randon.uniform() will generate a negative floating number.

## Generate with duplicates

There are many ways to generate a list of random numbers with duplicate elements. You can use random.randrange() or random.choice() to create list of duplicate elements. Check out the code below:

### Using randrange()

Code:

```import random
my_list = [random.randrange(10) for x in range(0, 10)]
print (sorted(my_list))
```

Output: It can be seen in the output that we have a list with duplicate elements. We have used the sorted() method to sort the list.

### Using choice()

Code:

```import random
my_list = [random.choice(range(10)) for x in range(0, 10)]
print (sorted(my_list))
```

Output: ## Generate without duplicates (Unique random numbers)

When creating a list of random numbers, there is a chance for duplicate elements in the list. To avoid a list of duplicate elements, the random module defines a function called sample() that creates a list without repeating any elements.

Syntax:

```random.sample(sequence, k)
```
• sequence: is iterable. It can be a list, tuple, set, or string, etc.
• k: is the size (length) of the resultant list. k should not be greater than the size of the input list.

The return type of random.sample() is a list of elements without any duplicate elements. The following example demonstrates the use of sample() method on a list, string, and tuple.

Code:

```import random
mylist = [1, 2, 3, 4, 5]
print (random.sample(mylist, 4))
mytuple = ('egg', 'apple', 'banana', 'orange', 'cherry')
print (random.sample(mytuple, 3))
mystring = "LikeGeeks"
print (random.sample(mystring, 3))
```

Output: Note that when we used the random.sample() method with strings, it shows some duplicates. Actually, it happens sometimes with strings.

## Random number on circle

Using the random module, we can generate random points in a circular distribution. In this section, we will find random coordinates of a circle. Consider the example below:

Code:

```import random
import math
center_x = 3
center_y = 5
rand_angle = 2 * math.pi * random.random()
cord_x = rand_radius * math.cos(rand_angle) + center_x
cord_y = rand_radius * math.sin(rand_angle) + center_y
print("Random Points on circle: ", (cord_x, cord_y))
```

Output: In this example, we have generated a random radius and a random angle to find the coordinates of a circle using general mathematical functions.

## Shuffle Numbers

We can shuffle the elements in the given sequence or iterable by using the shuffle() method of the random module. The syntax for the shuffle() method is given below:

Syntax:

```random.shuffle(sequence, function)
```
• sequence: is an iterable such as a list, set, or tuple.
• function: is optional and it defaults to random(). It returns a value ranging from 0.0 to 1.0.

The method returns nothing. It will just shuffle the original list. By shuffling, we mean that the elements will be changed from their original position.

Code:

```import random
my_list = ['a', 'b', 'c', 'd', 'e']
print ("List before shuffling", my_list)
random.shuffle(my_list)
print ("List after shuffling", my_list)
```

Output: ## Generate true random number

Generating random numbers based on arithmetical parameters are quite easy to guess as we mentioned at the begining. To generate a true random number, the computer has to measure physical parameters.

For example, you want to generate a true random number, you can measure your mouse movement, the input response from input devices, etc.
In Python, you can use the class random.SystemRandom() to generate true random numbers.

This class uses resources provided by the operating system to generate random numbers and does not depend on any software. These numbers cannot be reproduced.
You can use all methods of the random module with random.SystemRandom(). The difference is SystemRandom() uses OS resources.

Code:

```import random
trng = random.SystemRandom()
trng.randint(1, 15)
``` This code generates a true random number between 1 and 15. Similarly, you can generate true floating random numbers using random.SystemRandom().random:

`random.SystemRandom().random()`

Now you learned how to generate both pseudorandom and true random numbers using Python.

I hope you find the tutorial useful. Keep coming back.