## Introduction

Working with random numbers is an important part of most applications today. Games are one of the most common user of them. Generating random numbers effectively is likewise an important concern of today's computing world.

In this chapter, we shall see how to work with random numbers in Python. Specifically, we'll see how to generate a random float in the range `[0, 1)` and how to generate random integers in a given arithmetic progression, including the progression of natural numbers.

## What are pseudo-random numbers?

When we take the term 'random', we basically mean something that's not predictable — it's purely based on chance.

Random numbers generated by computers are surely random, but predictable.

Now this might confuse you — and it should because it goes against our usual understanding of the term 'random'. When something is random, how is it predictable?

Random numbers generated by computers simply form a sequence where consecutive elements don't follow any given pattern — that is, they're random. However, there comes a point when the sequence starts to repeat itself.

In other words, it's predictable after a given length of elements.

Hence, the random numbers generated by computers are random, but predictable (after some point). We can't call them purely random.

Such random numbers are termed specially — they're called pseudo-random numbers.

A pseudo-random number is a computer-generated random number.

An algorithm that generates a pseudo-random number is called a pseudo-random number generator, or simply PRNG.

Almost all programming languages today use PRNGs to generate random numbers. Python is no exception.

How exactly do these algorithms work is beyond the scope of this chapter. They use complex math and theories from sophisticated areas of mathematics such as number theory, congruences, and much more geeky stuff.

Now the next time, whenever you encounter a random number in Python, or any other programming language, you would know that it's a pseudo-random number — not a pure random number.

## The `random` module

The fuel of random numbers in Python is the `random` module. Without it, one can't imagine randomness in Python, unless that person is a PRNG programmer!

Hence, we start by importing the `random` module into our script:

``import random``

One this is done, we can validly operate on random numbers.

Now there are a couple of function to get a random number using the `random` module. The section below explores some of those functions one by one.

Actually, there is one more way to generate random numbers in Python which is considered more secure than `random`. It is the `urandom()` function of the `os` module. However, it's specific to cryptographic purposes, so we won't need it.

## A random number in [0, 1)

The most basic function of the `random` module is the `random()` function.

It returns a float in the range `[0, 1)` (greater than or equal to `0` and lesser than `1`).

Let's see it in action:

``````import random

# a random number
print(random.random())

# another random number
print(random.random())``````
0.8171490774449344
0.34983672178530134

Using the `random()` function and a bit of arithmetic, one can generate random numbers in any given range. The exercises below demonstrate this.

Construct a function `random_number()` that returns a random float between `0` (inclusive) and `100` (exclusive).

As we saw above, `random()` returns a float in the range `[0, 1)`. If we multiply its result with `100` we get a float in the range `[0, 100)`.

So, this is how we'll define the `random_number()` function:

``````import random

def random_number():
return random.random() * 100``````

Although, a bit of arithmetic of `random()` allows us to generate any sort of random number in Python, it's not really straightforward and out-of-the-box. Fortunately, Python provides a couple of other functions to produce random numbers in given ranges and of given types.

Let's see them..

## A random integer

The `randint()` function takes in two arguments and returns a random integer between these numbers (both inclusive).

``random.randint(lower_limit, upper_limit)``

`randint()` is a handy way to get random integers in Python.

Consider the code below:

``````import random

# random integer between 0 and 5
print(random.randint(0, 5))

# random integer between 20 and 30
print(random.randint(20, 30))``````
4
24

First we get a random number between `0` and `5` (both inclusive), and then we get another one between `20` and `30`.

Let's call `random.randint(20, 30)` a couple of times to see what values do we get in a run:

``random.randint(20, 30)``
21
``random.randint(20, 30)``
30
``random.randint(20, 30)``
25
Before working with the `random` module in the interactive shell, make sure that you have it imported via `import random`.

How to generate a random integer between `0` (inclusive) and `10` (exclusive) using `randint()`?

• Using `randint(0, 9)`
• Using `randint(0, 10)`

## The `randrange()` function

Python enables one to get a random integer in a given arithmetic progression using the `randrange()` function.

It works just like the `range()` function — except for that it doesn't return a sequence, but rather a randomly selected item from the sequence.

Consider the example below:

``````import random

# random item from the sequence below:
# 0, 1, 2, 3, 4, 5, 6, 7, 8
print(random.randrange(9))``````
5

First think of what does `range(9)` define. It defines a sequence of the integers from `0` to `8` (both inclusive). `randrange()` accordingly selects one item from this sequence.

Now let's consider another sequence:

``````import random

# random item from:
# 0, 2, 4, 6, 8, 10
print(random.randrange(0, 11, 2))
print(random.randrange(0, 11, 2))
print(random.randrange(0, 11, 2))``````
2
10
0

As before, first let's see what does `range(0, 11, 2)` define. It defines all even integers from `0` to `10` (both inclusive). Thereby, `randrange(0, 11, 2)` returns a randomly selected item from this sequence of evens.

#### `randrange()` doesn't compute a sequence!

One might be tempted to think that `randrange()` creates an actual sequence and then selects a number from it. However, this is not the case.

Instead, `randrange()` uses `random()` internally and a bit of elementary arithmetic to return a random integer in a given arithmetic progression.

## Moving on

These are not the only functions of the `random` module. There are a couple more, however they are related to lists and statistics and other concepts that we shall explore later on.