Как в Python работать со случайными числами
Содержание:- Случайные числа
- Генерация случайных чисел и данных в Python
- Криптографическая генерация случайных данных
В рамках полезных советов по изучению Python рассмотрим возможности языка при работе со случайными числами и данными.
Случайные числа
Случайные числа не случайны, как бы парадоксально это ни прозвучало. Точнее, те последовательности чисел, которые получают программным методом в языках программирования, истинно случайными не являются. Они называются псевдослучайными, поскольку привязаны, как правило, к системному времени, вычисляются с помощью алгоритмов, а их последовательности цикличны, т. е. повторяются с каким-либо периодом и подчиняются определенному закону распределения, например нормальному или равномерному.
Примеры истинно случайных чисел встречаются в природе при регистрации шумов: радиации, электрического тока, космического излучения, атмосферных колебаний и т. д. Но использование таких чисел нецелесообразно ввиду дороговизны их получения и обработки, больших временных затрат и невозможности воспроизвести полученную ранее последовательность. На практике используют либо псевдослучайные числа, либо числа, порожденные физическим источником, от которых в дальнейшем воспроизводится псевдослучайная последовательность.
В статье условимся псевдослучайные числа называть случайными.
Случайные числа находят свое применение в:
- системах математического моделирования и симуляции физических процессов;
- криптографии;
- теории вероятностей;
- теории игр;
- биологии (наследование, мутации).
Генерация случайных чисел и данных в Python
В языке Python существует два основных способа работы со случайными данными: модуль Nympy.random и библиотека random Python.
Модуль Random
Random содержит порядка 20 различных функций для работы со случайными целыми и вещественными числами.
Для работы с ним его нужно импортировать:
import random
В качестве первого примера обычно приводят функцию random() – генерирует вещественное число в отрезке от 0 до 1:
print (random.random())
- 0.17689854910005198
Для запоминания конкретного числа существует метод seed(). Это своего рода метка, с помощью которой можно вновь воспроизвести значение, сохраненное в памяти:
random.seed (1488)
print(random.random())
print(random.random())
random.seed(1488)
print(random.random())
- 0.2750168266116314
- 0.1435651490856893
- 0.2750168266116314
Чтобы сгенерировать число с плавающей точкой в произвольном промежутке, например от 0 до 100, можно использовать метод uniform():
print(random.uniform(0, 100))
- 75.1112561853534
Создавать целые числа можно при помощи randint() – отрезок, randrange() – интервал:
print(random.randint(0, 100))
print(random.randrange(0, 100))
- 85
- 41
Метод randrange() позволяет также определить шаг интервала:
print(random.randrange(0, 100, 10))
print(random.randrange(0, 100, 10))
- 80
- 30
Одна из распространенных задач, которую могут дать на собеседовании, – случайный выбор из списка. Допустим, в коробке находятся 3 белых шара и один черный. Какова вероятность вытащить черный? Для этого потребуется создать цикл из большого количества повторений (хотя бы 1000) и разделить количество выбранных черных шаров на общее количество повторений:
import random
number = 1000
black_num = 0
for i in range(0,number):
ball = random.choice([‘black’, ‘white’, ‘white’, ‘white’])
if ball == ‘black’:
black_num += 1
print (black_num / number)
- 0.243
Как видим, ответ получился недалеким от истины – 0,25.
Вывод случайным образом нескольких элементов последовательности списка осуществляется при помощи sample():
list_of_nums = [1, 2, 3, 4, 5, 6]
print(random.sample(list_of_nums, 4))
- [2, 3, 5, 4]
Как видим, получилась новая последовательность, где каждое число было сформировано случайным образом без повторов.
Помимо случайной выборки можно перемешать элементы последовательности чисел списка случайным образом с помощью shuffle():
list_of_nums = [1, 2, 3, 4, 5, 6]
random.shuffle(list_of_nums)
print(list_of_nums)
- [6, 1, 2, 4, 5, 3]
Рассмотрим еще одну задачу. На этот раз нам будут известны веса событий. Допустим, у нас есть такой «крапленый» игральный кубик, где стороны выпадают с разными вероятностями:
- 1 – p = 0,05;
- 2 – p = 0,05;
- 3 – p = 0,1;
- 4 – p = 0,2;
- 5 – p = 0,2;
- 6 – p = 0,4.
Требуется определить количество выпадений шестерок из, допустим, 10 000 бросков:
import random
nums = 10000
six_count = 0
for i in range(0,nums):
cube_side = random.choices([‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’],
weights = [0.05, 0.05, 0.1, 0.2, 0.2, 0.4])
if cube_side == [‘6’]:
six_count += 1
print (six_count)
- 3957
В этот раз мы использовали метод choices, в который дополнительно можно передать веса weights вероятностных событий.
Numpy.Random
Используется при необходимости генерации массива псевдослучайных чисел:
import numpy
# Матрица размерностью 3×3 значений с плавающей точкой от 0 до 1
rand_arr = numpy.random.rand(3, 3)
print (rand_arr)
- [[0.03449598 0.88556689 0.66734693]
[0.82412437 0.66913243 0.70730428]
[0.69094665 0.09120329 0.034072 ]]
# Матрицу размером 3×3 случайных вещественных чисел в промежутке от 0 до 100
rand_arr = numpy.random.uniform(0, 100, size = (3, 3))
print (rand_arr)
- [[76.09088217 52.40791111 15.93937122]
- [ 6.13460555 38.29344245 74.68885777]
- [79.71226036 98.59500501 50.48377588]]
# Массив размером 3×3 псевдослучайных целых чисел в заданном диапазоне от 0 до 100
rand_arr = numpy.random.randint(0, 100, size = (3, 3))
print (rand_arr)
- [[93 73 11]
- [81 9 96]
- [89 96 43]]
Случайная строка
Помимо чисел можно генерировать случайно еще буквы:
import random
import string
letter = string.ascii_letters
rand_ascii = random.choice(letter)
print(rand_ascii)
- f
Или целые строки:
letter = string.ascii_letters
rand_string = ».join(random.choice(letter) for i in range(10))
print(rand_string)
- rplmzkmget
Криптографическая генерация случайных данных
Для того чтобы генерировать криптографически стойкие случайные данные (числа, символы), например для создания паролей, можно использовать несколько методов:
- модуль secrets – генерирует случайные байты;
- модуль os.urandom() и SystemRandom() – генерируемые данные привязаны к конкретной операционной системе.
Примеры:
import random
import string
letter = string.ascii_lowercase
# Случайно сгенерированная надежная строка
rand_string = ».join(random.SystemRandom().choice(letter) for i in range(10))
print(rand_string)
- Omqbcwkwtq
import secrets
letter = secrets.token_bytes(10) # случайные байты
print (letter)
letter = secrets.token_hex(10) # случайная строка в 16-ричной форме
print (letter)
letter = secrets.token_urlsafe(10) # случайная URL-строка
print (letter)
- b’x9cx17zx94Tnx91;v<‘
- 0bcc1e558af5f9f77112
- 528854MP3gZ5iA
Например, можно сгенерировать случайный пароль следующим образом:
import random
import string
import secrets
symbols = string.ascii_letters + string.digits
key_word = ».join(secrets.choice(symbols) for i in range(10))
print(key_word)
- OrRwiG4nJ8
Более подробно ознакомиться с возможностями использования случайных данных при решении статистических и криптографических задач, с которыми программистам приходится сталкиваться в работе, разобрать таски, часто используемые в тестировании на собеседовании, можно на курсах DevEducation. Здесь на практических примерах поясняются тонкости и аспекты использования тех или иных возможностей языка.