Генератор псевдослучайных чисел – random

В компьютерных программах нередко требуется эмуляция случайности. Например, при разработке игр. Если в программе имеется некий генератор, т. е. производитель, случайного числа, то, используя полученное таким образом число, можно выбирать ту или иную ветку выполнения программы, или произвольный объект из коллекции. Другими словами, главное – сгенерировать число. Эмуляция случайности иного рода основывается на нем.

Мы наверняка не знаем, есть ли в природе случайность, или она нам только кажется из-за ограниченности наших знаний. Мы только знаем, что в программировании настоящей случайности нет. Неоткуда взяться произвольному числу, нельзя запрограммировать его появление из ниоткуда. Можно лишь создать программу, которая в результате применения сложной формулы к «зерну» будет выдавать число, и нам будет казаться, что это число случайно.

«Зерно» – это исходные данные для формулы. Им может быть, например, системное время в миллисекундах, которое постоянно меняется. Следовательно, «зерно» будет постоянно разным. Или программист может задавать его самостоятельно.

Подобную программу (в реальности модуль или функцию) называют генератором псевдослучайных чисел. В состав стандартной библиотеки языка Python входит модуль random. Он содержит множество функций, связанных с эмуляцией случайности (например, «перемешивание» элементов последовательности), а не только функции генерации псевдослучайных чисел.

В этом уроке будут рассмотрены функции random(), randrange() и randint() из модуля random. Обратите внимание, что модуль random содержит одноименную функцию random(). Так бывает.

Чтобы обращаться к функциям, надо импортировать модуль random:

import random
1

Или импортировать отдельные функции из него:

from random import random, randrange, randint
1

Функции для получения целых «случайных» чисел – randint() и randrange()

Функции randint() и randrange() генерируют псевдослучайные целые числа. Первая из них наиболее простая и всегда принимает только два аргумента – пределы целочисленного диапазона, из которого выбирается любое число:

import random

print(random.randint(0, 10))    # 6 или другое случайное число от 0 до 10.
1
2
3

или (если импортировались отдельные функции):

from random import randint

print(randint(100, 200))        # 115 или другое случайное число от 100 до 200.
1
2
3

В случае randint() обе границы включаются в диапазон, т. е. на языке математики отрезок описывается как [a; b].

Числа могут быть отрицательными:

import random

print(random.randint(-100, 10))     # -83
print(random.randint(-100, -10))    # -38
1
2
3
4

Но первое число всегда должно быть меньше или, по-крайней мере, равно второму. То есть a <= b.

Функция randrange() сложнее. Она может принимать один аргумент, два или даже три. Если указан только один, то она возвращает случайное число от 0 до указанного аргумента. Причем сам аргумент в диапазон не входит. На языке математики – это [0; a):

import random

print(random.randrange(10))     # 4
1
2
3

Или:

from random import randrange

print(randrange(5))             # 0
1
2
3

Если в randrange() передается два аргумента, то она работает аналогично randint() за одним исключением. Верхняя граница не входит в диапазон, т. е. [a; b):

import random

print(random.randrange(5, 10))  # 9
print(random.randrange(1, 2))   # 1
1
2
3
4

Здесь результатом второго вызова всегда будет число 1.

Если в randrange() передается три аргумента, то первые два – это границы диапазона, как в случае с двумя аргументами, а третий – так называемый шаг. Если, например, функция вызывается как randrange(10, 20, 3), то «случайное» число будет выбираться из чисел: 10, 13, 16, 19.

print(random.randrange(10, 20, 3))  # 13
print(random.randrange(10, 20, 3))  # 19
print(random.randrange(10, 20, 3))  # 10
1
2
3

Функция random() – «случайные» вещественные числа

Чтобы получить случайное вещественное число, или, как говорят, число с плавающей точкой, следует использовать функцию random() из одноименного модуля random языка Python. Она не принимает никаких аргументов и возвращает число от 0 до 1, не включая 1:

print(random.random())      # 0.17855729241927576
print(random.random())      # 0.3310978930421846
1
2

или:

print(random())         # 0.025328854415995194
1

Результат содержит много знаков после запятой. Чтобы его округлить, можно воспользоваться встроенной в Python функцией round():

import random

a = random.random()
print(a)                # 0.8366142721623201
print(round(a, 2))      # 0.84
print(round(random.random(), 3))    # 0.629
1
2
3
4
5
6

Чтобы получать случайные вещественные числа в иных пределах, отличных от [0; 1), прибегают к математическим приемам. Так если умножить полученное из random() число на любое целое, то получится вещественное в диапазоне от 0 до этого целого, не включая его:

print(random.random() * 10)     # 2.510618091637596
print(random.random() * 10)     # 6.977540211221759
1
2

Если нижняя граница должна быть отличной от нуля, то число из random() надо умножать на разницу между верхней и нижней границами, после чего прибавить нижнюю:

print(random.random() * (10 - 4) + 4)   # 9.517280589233597
print(random.random() * (10 - 4) + 4)   # 6.4429124181215975
print(random.random() * (10 - 4) + 4)   # 4.9231983600782385
1
2
3

В данном примере число умножается на 6. В результате получается число от 0 до 6. Прибавив 4, получаем число от 4 до 10.

Пример получения случайных чисел от -1 до 1:

print(random.random() * (1 + 1) - 1)    # -0.673382618351051
print(random.random() * (1 + 1) - 1)    # 0.34121487148075924
print(random.random() * (1 + 1) - 1)    # -0.988751324713907
print(random.random() * (1 + 1) - 1)    # 0.44137358363477674
1
2
3
4

Нижняя граница равна -1. При вычитании получается +. Когда добавляется верхняя граница, то плюс заменяется на минус ( +(-1) = - 1).

Для получения псевдослучайных чисел можно пользоваться исключительно функцией random(). Если требуется получить целое, то всегда можно округлить до него с помощью round() или отбросить дробную часть с помощью int():

print(int(random.random() * 100))       # 61
print(round(random.random() * 100 - 50) # -33
1
2

Упражнения

  1. Используя функцию randrange() получите псевдослучайное четное число в пределах от 6 до 12. Также получите число кратное пяти в пределах от 5 до 100.

  2. Напишите программу, которая запрашивает у пользователя границы диапазона и какое число: целое или дробное, он хочет получить. Выводит на экран подходящее случайное число.

    Enter the number from: -3
    Enter the number to: 10
    Enter number '1' - integer or 2 - float: 2
    -3.45
    
    1
    2
    3
    4
  3. Используя только функцию random(), т.е. не используя функции: randrange(), randint() и др. Вывод реализовать в консоль. Напишите программу генерирующую случайные числа в указанных диапазонах:

    • генератор целых чисел в диапазоне от 0 до 7;
    • генератор целых чисел в диапазоне от 10 до 30;
    • генератор целых чисел в диапазоне от -7 до 7;
    • генератор целых чисел в диапазоне от 0 до 10 с шагом 2;
    • генератор целых чисел в диапазоне от 0 до 25 с шагом 3;
    • генератор целых чисел в диапазоне от 20 до 40 с шагом 4;
    • генератор целых чисел в диапазоне от -40 до 0 с шагом 5;
    • генератор целых чисел в диапазоне от -14 до 10 с шагом 2;
    • генератор дробных чисел в диапазоне от 0 до 4.5 с шагом 0.5;
    • генератор дробных чисел в диапазоне от 7 до 21 с шагом 0.25;
    • генератор дробных чисел в диапазоне от -2.5 до 2.5 с шагом 1.25;
  4. Напишите оконное приложение для генерации разных чисел задаваемых пользователем. Программа должна содержать виджеты:

    • однострочное текстовое поля для ввода начального диапазона;
    • однострочное текстовое поля для ввода конечного диапазона;
    • однострочное текстовое поля для ввода шага числа;
    • кнопки при нажатии на которую происходит генерация числа;
    • метка (label) для вывода результата генерации;
    • Диапазоны и шаги допустимо задавать целыми или дробными числами;
    • Реализуйте все необходимы проверки. Программа не должна выдавать ошибки при отсутствии вводимых данных и/или не корректных данных: "a", "1 0", "- 5", "0,0" и т.п.

    tkinter_random