Генерируем случайное число java
Содержание:
- Функция srand().
- Вопрос 1. Что такое случайные числа?
- Random_device – генератор истинно случайных чисел
- Генерация случайных чисел в заданном диапазоне
- Зачем нужны функции getstate() и setstate() ?
- Алгоритм произвольного выбора
- std::generate
- Почему в IT все числа неслучайные
- Случайные числа в си
- Создание случайного пароля пользователя
- Игра в кости с использованием модуля random в Python
- Вопрос 3. Псевдослучайные числа
- Инициализация генератора и seed
- 16-битный код
- Время как источник случайности
- Игра в кости с использованием модуля random в Python
- Алгоритм перемешивания
- Примеры использования модуля random.
Функция srand().
Да, каждый раз появляются одни и те же одинаковые числа. «Так себе генератор!» – скажете вы. И будете не совсем правы.
Действительно, генерируются всё время одинаковые числа. Но мы можем на это повлиять, для этого используется функция srand(), которая также определена в заголовочном файле stdlib.h. Она инициализирует генератор случайных чисел начальным числом.
Скомпилируйте и запустите несколько раз вот эту программу:
Листинг 5.
#include <stdio.h> #include <stdlib.h> int main(void) { srand(2); /* генерируем пять случайных целых чисел из отрезка */ printf("%d\n", 80 + rand()%(100 - 80 + 1)); printf("%d\n", 80 + rand()%(100 - 79)); printf("%d\n", 80 + rand()%21); printf("%d\n", 80 + rand()%21); printf("%d\n", 80 + rand()%21); }
Теперь поменяйте аргумент функции srand() на другое число (надеюсь вы ещё не забыли, что такое аргумент функции?) и снова скомпилируйте и запустите программу. Последовательность чисел должна измениться. Как только мы меняем аргумент в функции srand – меняется и последовательность. Не очень практично, не правда ли? Чтобы изменить последовательность, нужно перекомпилировать программу. Вот бы это число туда подставлялось автоматически.
И это можно сделать. Например, воспользуемся функцией time(), которая определена в заголовочном файле time.h.
Данная функция, если ей в качестве аргумента передать NULL, возвращает количество секунд, прошедших c 1 января 1970 года. Вот посмотрите, как это делается.
Листинг 6.
#include <stdio.h> #include <stdlib.h> #include <time.h> // чтобы использовать функцию time() int main(void) { srand(time(NULL)); /* генерируем пять случайных целых чисел из отрезка */ printf("%d\n", 80 + rand()%(100 - 80 + 1)); printf("%d\n", 80 + rand()%(100 - 79)); printf("%d\n", 80 + rand()%21); printf("%d\n", 80 + rand()%21); printf("%d\n", 80 + rand()%21); }
Вы спросите, а что такое NULL? Резонный вопрос. А я вам пока отвечу, что это специальное зарезервированное слово такое. Могу ещё сказать, что им обозначает нулевой указатель, но т.к. это для вас никакой информации не несёт, то на данный момент рекомендую об этом не думать. А просто запомнить как некоторый хитрый трюк. В будущих уроках мы остановимся на этой штуке поподробнее.
Вопрос 1. Что такое случайные числа?
Сложность: 1/3
Что нужно помнить: случайные числа — это математическое понятие, и их не следует путать с обыденными, произвольными числами. Случайное число в математике и программировании — это:
- число из определённого диапазона,
- у которого есть определённая вероятность выпадения.
Другими словами, существует закон или правило, которое называется «функцией распределения» или просто «распределением». И это самое распределение «раздаёт» каждому числу из диапазона определённую вероятность выпадения.
В качестве диапазона значений математикам и программистам привычнее всего использовать диапазон действительных чисел от 0 до 1, но это могут быть и целые числа от 1 до 6, как в игральном кубике, или от 100 до 1 000 000 — и так далее. Главное, что и распределение, и диапазон известны заранее, а само число нет.
Итого: случайные числа — это искусственно полученная последовательность чисел из определённого диапазона, которая подчиняется одному из законов распределения случайной величины.
Random_device – генератор истинно случайных чисел
Все генераторы псевдослучайных чисел являются детерминированными. То есть имеют определение. Или другими словами, получение случайных чисел основано на математических алгоритмах. Random_device же является недетерминированным. Он создает числа на основе стохастических (случайных с др.-греч.) процессов. Такими процессами могут быть изменения фазы или амплитуды колебаний тока, колебания молекулярных решеток, движения воздушных масс в атмосфере и т.д.
Очевидно, что не у каждого компьютера и не в каждой системе может быть встроена возможность получить случайное число на основе стохастического процесса. Поэтому прибегать к использованию random_device стоит только в случае необходимости. Его работа может отличаться от системы к системе, от компьютера к компьютеру, а может и вовсе быть недоступной. Поэтому при использовании генератора истинно случайных чисел нужно обязательно предусмотреть обработку ошибок.
Генерация случайных чисел в заданном диапазоне
Существует несколько способов генерации случайного (псевдослучайного) числа:
- Использование метода random() из класса математических функций Math , находящемся в пакете java.lang.
- Использование метода random() из класса Random , находящемся в пакете java.util.Random.
- Использование генератора случайных чисел класса SecureRandom , предназначенного для целей криптографии и, находящегося в пакете java.security. SecureRandom (здесь не рассматривается).
Рассмотрим методы генерации случайных чисел.
Класс Math. Метод random()
Метод random() класса Math возвращает псевдослучайное число типа double в диапазоне 0 ≤ Math.random()
Пример 1. Несколько случайных чисел
Случайное число № 1: 0.9161994380531232 Случайное число № 2: 0.24340742865928744 Случайное число № 3: 0.9783627451986034
Пример 2. Случайное число x в диапазоне a ≤ x ≤ b
Для генерации целого случайного числа x в заданном диапазоне a ≤ x ≤ b, обычно используется следующая зависимость:
x = a + (int)(Math.random()*((b — a) + 1)).
Получим случайное число x в диапазоне: 10 ≤ x ≤ 20 (a=10, b=20).
Результат.Случайное число x: 19
Класс Random. Метод random()
Это наиболее часто используемый класс для генерации псевдослучайный чисел с равномерной функцией распределения. Имеется метод nextGaussian() , который моделирует функцию нормального распределения.
Основными методами этого класса являются:
- int nextInt( ) — возвращает следующее случайное значение ix типа int в диапазоне -2147483648 ≤ ix
- int nextInt(int n) — возвращает следующее случайное значение ix типа int в диапазоне 0 ≤ ix
- float nextFloat() — возвращает следующее случайное значение fx типа float в диапазоне 0.0 ≤ fx
- double nextDouble() — возвращает следующее случайное значение dx типа double в диапазоне 0.0 ≤ dx
- boolean nextBoolean() — возвращает следующее случайное значение типа boolean
Для получения случайных чисел необходимо:
- Подключить библиотеку случайных чисел. Пишем до определения класса. import java.util.Random;
- В классе создать объект rand случайных чисел Random rand = new Random();
- Далее использовать необходимые методы объекта rand.
Пример 1. Несколько случайных чисел разных типов.
Случайное число ix: 1438841988 Случайное число dx: 0.6120986135409442 Случайное число fx: 0.103119016 Случайное число bx: true
Пример 2. Случайное число x в диапазоне a ≤ x ≤ b.
Для генерации целого случайного числа x в заданном диапазоне a ≤ x ≤ b, обычно используется следующая зависимость:
тип int int x = a + rand.nextInt(b — a + 1).
тип double double y = a + rand.nextInt(b — a).
Случайное число x: 12 Случайное число dx: 17.505847041626733
Для типа double будет выведено случайное число в виде:
что неудобно. Для приемлемого представления используется форматный вывод, позволяющий выводить числа с заданной точностью.
Форматный вывод
Пакет java.io содержит класс PrintStream , который содержит методы printf и forma t, позволяющие выводить числа с заданной точностью. Рассмотрим метод format(). Синтаксис метода
System.out.format(String format, Object. args),
format — это строка — шаблон, согласно которому будет происходить форматирование, args — это список переменных, для вывода по заданному шаблону.
Строка — шаблон содержит обычный текст и специальные форматирующие символы. Эти символы начинаются со знака процента (%) и заканчиваются конвертором — символом, который определяет тип переменной для форматирования. Вот некоторые конверторы:
Источник
Зачем нужны функции getstate() и setstate() ?
Если вы получили предыдущее состояние и восстановили его, тогда вы сможете оперировать одними и теми же случайными данными раз за разом. Помните, что использовать другую функцию random в данном случае нельзя. Также нельзя изменить значения заданных параметров. Сделав это, вы измените значение состояния .
Для закрепления понимания принципов работы и в генераторе случайных данных Python рассмотрим следующий пример:
Python
import random
number_list =
print(«Первая выборка «, random.sample(number_list,k=5))
# хранит текущее состояние в объекте state
state = random.getstate()
print(«Вторая выборка «, random.sample(number_list,k=5))
# Восстанавливает состояние state, используя setstate
random.setstate(state)
#Теперь будет выведен тот же список второй выборки
print(«Третья выборка «, random.sample(number_list,k=5))
# Восстанавливает текущее состояние state
random.setstate(state)
# Вновь будет выведен тот же список второй выборки
print(«Четвертая выборка «, random.sample(number_list,k=5))
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
importrandom number_list=3,6,9,12,15,18,21,24,27,30 print(«Первая выборка «,random.sample(number_list,k=5)) state=random.getstate() print(«Вторая выборка «,random.sample(number_list,k=5)) random.setstate(state) print(«Третья выборка «,random.sample(number_list,k=5)) random.setstate(state) print(«Четвертая выборка «,random.sample(number_list,k=5)) |
Вывод:
Shell
Первая выборка
Вторая выборка
Третья выборка
Четвертая выборка
1 2 3 4 |
Перваявыборка18,15,30,9,6 Втораявыборка27,15,12,9,6 Третьявыборка27,15,12,9,6 Четвертаявыборка27,15,12,9,6 |
Как можно заметить в результате вывода — мы получили одинаковые наборы данных. Это произошло из-за сброса генератора случайных данных.
Алгоритм произвольного выбора
Часто возникает задача произвольного выбора ранее заданных элементов массива. Причем необходимо предусмотреть отсутствие повторений в выборе этих элементов.
Алгоритм такого выбора состоит в следующем:
- Выбираем произвольно индекс элемента массива
- Если элемент с таким индексом уже был ранее выбран, двигаемся вправо, пока не дойдём до следующего не выбранного элемента. При этом следим за тем, чтобы «движение вправо» не вышло за границы массива. Если фиксируется выход за границы массива, начинаем просмотр элементов массива с начала.
- Выбираем элемент
- Фиксируем элемент как выбранный
- Повторяем указанные действия для всех остальных элементов
Реализации на Си
В результате получаем новый массив b, сформированный произвольной выборкой элементов массива a.
123456789101112131415161718192021222324252627282930313233
#include <stdio.h>#include <stdlib.h>#include <time.h>#define SIZE 20int main() { int a; int b; // результирующий массив srand(time(NULL)); // Заполняем массив последовательными значениями от 1 до 20 for (int i = 0; i < SIZE; i++) { a = i + 1; printf(«%2d «, a); } for (int i = 0; i < SIZE; i++) { int ind = rand() % 20; // выбираем произвольный индекс while (a == -1) // пока элемент «выбран» { ind++; // двигаемся вправо ind %= 20; // если дошли до правой границы, возвращаемся в начало } b = a; // записываем следующий элемент массива b a = -1; // отмечаем элемент массива a как «выбранный» } printf(«\n»); // Выводим получившийся массив for (int i = 0; i < SIZE; i++) printf(«%2d «, b); getchar(); return 0;}
Алгоритмизация
std::generate
Пример: заполнение вектора СЧ и вывод содержимого на экран с нахождением максимального и минимального элементов
#include <iostream>
#include <random>
#include <algorithm>
#include <iterator>
#include <vector>
#include <cstddef>
int main()
{
std::mt19937 gen { std::random_device()() };
std::uniform_int_distribution<int> uid(, 100);
const std::size_t N = 50;
std::vector<int> v(N);
// генерируем 50 СЧ
std::generate(v.begin(), v.begin() + N, () -> int
{ return uid(gen); } );
// выводимсодержимоевекторанаэкран
std::copy(v.begin(), v.begin() + N, std::ostream_iterator<int> (std::cout, » «) );
auto mm = std::minmax_element(v.begin(), v.begin() + N);
std::cout << «\nMin: » << *mm.first << «\nMax: » << *mm.second << std::endl;
}
Почему в IT все числа неслучайные
Казалось бы, что мешает использовать в программах случайные числа? К сожалению, процессор на это не способен: его поведение строго детерминировано и не допускает никаких случайностей.
- Для генерации по-настоящему случайных, ничем не связанных чисел операционной системе приходится использовать средства, недоступные обычным приложениям; такие случайные числа называются криптографически стойкими случайными числами
- Генерация системой таких случайных чисел работает медленно, и при нехватке скорости система просто отдаёт приложениями псевдослучайные числа либо заставляет их ожидать, пока появится возможность вернуть случайное число
Случайные числа в си
На этому уроке мы научимся использовать случайные числа в программах на си. Часто в программах, например играх, необходимо получить случайное число. В Си используется функция для определения натурального случайного числа в диапазоне от 0 до 32767.rand();
Чтобы использовать эту функцию необходимо указать заголовочный файл в начале программы stdlib.h
Чтобы получить случайное число в диапазоне от 0 до N-1 используется выражениеrand() % N;Пример программы 18 Программа на си для вывода последовательности случайных чисел в заданном диапазоне#include <conio.h>
#include <stdlib.h>
#include <stdio.h>
main()
{
int n;
int m;
int i;
int ran;
printf («Введите границу диапазона\n «);
scanf («%d», &n);
printf («Введите сколько нужно вывести чисел\n»);
scanf («%d», &m);
for (i=1; i<=m; i++)
{
ran=rand()%n;// задаем случайное число в диапазоне от 0 до n
printf («%d\n», ran);
}
getch();
}
Следует заметить, что данная функция будет всегда выдавать одну и ту же последовательность, при каждом запуске программы. Это обусловлено тем, что каждое последующее число рассчитывается по формуле в зависимости от предыдущего. Иногда, необходимо выдавать всегда разные непредсказуемые случайные числа. Для этого можно использовать системное время компьютера.
Чтобы вызвать системное время компьютера (например секунды) используется заголовочный файл time.h Объявить его в начале программы #include <time.h>
Использовать функцию, которую необходимо разместить в начале программы.
// функция, выдающая системное время секундыint sec()
{
time_t t;
struct tm *t_m;
t=time(NULL);
t_m=localtime(&t);
return t_m->tm_sec;
}
Далее в программе, где нам нужно задать случайное число мы используем выражение((rand()+sec())%NПример программы 19 Игра на си орел решка Программа имитирует подбрасывание монетки Орел Решка#include <graphics.h>
#include <conio.h>
#include <time.h>
// функция выдающая системное время секунды
int sec()
{
time_t t;
struct tm *t_m;
t=time(NULL);
t_m=localtime(&t);
return t_m->tm_sec;
}
main()
{
int r;// выбор компьютера
int ans; // ответ на вопрос о продолжении игры
ans=1;
// игра продолжается пока ответ на продолжении игры 1
while(ans==1)
{
r=(rand()+sec()) % 2; // определяем случайное число в диапазоне от 0 до 1
printf(«%d «, r);
if (r==0) {printf(«Орел\n»);}
if (r==1) {printf(«Решка\n»);}
printf(«Сыграть еще раз? 1 — Да 2 — Нет\n»);
scanf(«%d», &ans);
}
getch();
}
Вернуться к содержанию Перейти к следующему уроку Процедуры и функции в Си
Полезно почитать по теме случайные числа в си примеры программИгра на си камень ножницы бумагаСлучайный графический узор на си
Поделиться
Создание случайного пароля пользователя
Для того , чтобы создать случайный пароль пользователя , можно использовать символы , представленные в модуле. В частности для знаков пунктуации, для букв и для цифр:
Затем мы можем объединить все эти символы в имени с именем :
Удалите любой из них, чтобы создать пул символов с меньшим количеством элементов.
После этого, мы можем использовать для генерации пароля. Для пароля длиной 10:
Обратите внимание , что другие процедуры , сделанные немедленно доступны в модуле — такие , как , и т.д. — не подходит для криптографических целей
За кулисами, эти процедуры использовать Вихрь Мерсенна ПСЧ , который не удовлетворяет требованиям , предъявляемым к CSPRNG . Таким образом, в частности, вам не следует использовать какие-либо из них для создания паролей, которые вы планируете использовать. Всегда используйте экземпляр , как показано выше.
Начиная с Python 3.6 доступен модуль `секреты`, который предоставляет криптографически безопасную функциональность. Процитировав , чтобы сгенерировать * «десятибуквенный буквенно-цифровой пароль, содержащий как минимум один символ в нижнем регистре, как минимум один символ в верхнем регистре и как минимум три цифры», * вы можете: импортировать строку alphabet = string.ascii_letters + string.digits, а True: пароль = » .join (выбор (алфавит) для i в диапазоне (10)) if (любой (c.islower () для c в пароле) и любой (c. isupper () для c в пароле) и sum (c.isdigit () для c в пароле)> = 3): break
Игра в кости с использованием модуля random в Python
Далее представлен код простой игры в кости, которая поможет понять принцип работы функций модуля random. В игре два участника и два кубика.
- Участники по очереди бросают кубики, предварительно встряхнув их;
- Алгоритм высчитывает сумму значений кубиков каждого участника и добавляет полученный результат на доску с результатами;
- Участник, у которого в результате большее количество очков, выигрывает.
Код программы для игры в кости Python:
Python
import random
PlayerOne = «Анна»
PlayerTwo = «Алекс»
AnnaScore = 0
AlexScore = 0
# У каждого кубика шесть возможных значений
diceOne =
diceTwo =
def playDiceGame():
«»»Оба участника, Анна и Алекс, бросают кубик, используя метод shuffle»»»
for i in range(5):
#оба кубика встряхиваются 5 раз
random.shuffle(diceOne)
random.shuffle(diceTwo)
firstNumber = random.choice(diceOne) # использование метода choice для выбора случайного значения
SecondNumber = random.choice(diceTwo)
return firstNumber + SecondNumber
print(«Игра в кости использует модуль random\n»)
#Давайте сыграем в кости три раза
for i in range(3):
# определим, кто будет бросать кости первым
AlexTossNumber = random.randint(1, 100) # генерация случайного числа от 1 до 100, включая 100
AnnaTossNumber = random.randrange(1, 101, 1) # генерация случайного числа от 1 до 100, не включая 101
if( AlexTossNumber > AnnaTossNumber):
print(«Алекс выиграл жеребьевку.»)
AlexScore = playDiceGame()
AnnaScore = playDiceGame()
else:
print(«Анна выиграла жеребьевку.»)
AnnaScore = playDiceGame()
AlexScore = playDiceGame()
if(AlexScore > AnnaScore):
print («Алекс выиграл игру в кости. Финальный счет Алекса:», AlexScore, «Финальный счет Анны:», AnnaScore, «\n»)
else:
print(«Анна выиграла игру в кости. Финальный счет Анны:», AnnaScore, «Финальный счет Алекса:», AlexScore, «\n»)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
importrandom PlayerOne=»Анна» PlayerTwo=»Алекс» AnnaScore= AlexScore= diceOne=1,2,3,4,5,6 diceTwo=1,2,3,4,5,6 defplayDiceGame() «»»Оба участника, Анна и Алекс, бросают кубик, используя метод shuffle»»» foriinrange(5) #оба кубика встряхиваются 5 раз random.shuffle(diceOne) random.shuffle(diceTwo) firstNumber=random.choice(diceOne)# использование метода choice для выбора случайного значения SecondNumber=random.choice(diceTwo) returnfirstNumber+SecondNumber print(«Игра в кости использует модуль random\n») foriinrange(3) # определим, кто будет бросать кости первым AlexTossNumber=random.randint(1,100)# генерация случайного числа от 1 до 100, включая 100 AnnaTossNumber=random.randrange(1,101,1)# генерация случайного числа от 1 до 100, не включая 101 if(AlexTossNumber>AnnaTossNumber) print(«Алекс выиграл жеребьевку.») AlexScore=playDiceGame() AnnaScore=playDiceGame() else print(«Анна выиграла жеребьевку.») AnnaScore=playDiceGame() AlexScore=playDiceGame() if(AlexScore>AnnaScore) print(«Алекс выиграл игру в кости. Финальный счет Алекса:»,AlexScore,»Финальный счет Анны:»,AnnaScore,»\n») else print(«Анна выиграла игру в кости. Финальный счет Анны:»,AnnaScore,»Финальный счет Алекса:»,AlexScore,»\n») |
Вывод:
Shell
Игра в кости использует модуль random
Анна выиграла жеребьевку.
Анна выиграла игру в кости. Финальный счет Анны: 5 Финальный счет Алекса: 2
Анна выиграла жеребьевку.
Анна выиграла игру в кости. Финальный счет Анны: 10 Финальный счет Алекса: 2
Алекс выиграл жеребьевку.
Анна выиграла игру в кости. Финальный счет Анны: 10 Финальный счет Алекса: 8
1 2 3 4 5 6 7 8 9 10 |
Игравкостииспользуетмодульrandom Аннавыигралаигрувкости.ФинальныйсчетАнны5ФинальныйсчетАлекса2 Аннавыигралаигрувкости.ФинальныйсчетАнны10ФинальныйсчетАлекса2 Аннавыигралаигрувкости.ФинальныйсчетАнны10ФинальныйсчетАлекса8 |
Вот и все. Оставить комментарии можете в секции ниже.
Вопрос 3. Псевдослучайные числа
Сложность: 3/3
Псевдослучайные числа — это, если очень упрощать, последовательность чисел, которая только выглядит случайной, а на самом деле каждое число в ней определяется алгоритмом, то есть вычисляется. Псевдослучайные последовательности цикличны: через какой-то период все числа повторяются в точности в том же порядке.
Библиотека random и модуль numpy.random содержат в себе генератор не истинно случайных, а именно псевдослучайных чисел.
Генерировать истинно случайные числа дорого и сложно. Основная трудность состоит в том, чтобы гарантировать отсутствие какого-либо цикла, правила или алгоритма. Чаще всего истинно случайные числа : шумов атмосферы, детекторов частиц, колебаний электрического тока или из космического излучения.
То, что псевдослучайная последовательность, в отличие от истинно случайной, воспроизводима, очень удобно для практических задач: часто нужно подать на вход ту же самую последовательность второй раз, чтобы посмотреть, как работает программа после добавления новых фич.
Визуализация работы генератора псевдослучайных чисел. Видите какую-нибудь закономерность? А она есть.Источник
Инициализация генератора и seed
Этап объявления, определения и создания сущностей зачастую рассматривается как нечто, не стоящее особого внимания. Но недостаточно вдумчивая инициализация генератора случайных чисел может сказаться на его надлежащей работе.
Первые 2 инициализации эквивалентны. И по большей части имеют отношение к вкусу или к стандартам написания красивого кода. А вот следующая инициализация в корне отличается.
«31255» — это называется seed (семя, первоисточник) — число, на основе которого генератор создает случайные числа. Ключевым моментом здесь является то, что при такой инициализации тип seed должен быть таким же или приводимым к типу, с которым работает генератор. Этот тип доступен через конструкцию decltype(e()), или result_of, или typename.
16-битный код
Для начала, как всегда, приведу код для реального режима, а вдруг кому-то да потребуется 🙂 При прямом неограниченном доступе кода к оборудованию все достаточно просто, поскольку архитектура x86 обеспечивает сразу несколько источников псевдослучайных чисел: это инструкция rdtsc (счетчик тиков), функция 0 прерывания 1Ah (счетчик тиков), порты 70-71h (системное время), порт 40h (таймер) и некоторые другие. Самый компактный генератор выглядит следующим образом:
in ax, 40h
1 | inax,40h |
Да, действительно подобное решение можно применять в случае, когда очень критична длина кода и требуется получить единственное случайное значение. Тем не менее описанная реализация имеет один существенный недостаток: когда вы применяете подобный генератор в потоковом режиме (требуется создать N-ое количество значений), вы сразу же обнаруживаете его линейность.
Более продвинутый собрат, который обеспечивает очень хороший разброс значений, следующий:
random:
push cx
push dx
push di
mov dx, word
or dx, dx
jnz @f
rdtsc
mov dx, ax
@@:
mov ax, word
or ax, ax
jnz @f
in ax, 40h
@@:
mul dx
inc ax
mov word , dx
mov word , ax
xor dx, dx
sub di, si
inc di
div di
mov ax, dx
add ax, si
pop di
pop dx
pop cx
ret
1 |
random pushcx pushdx pushdi movdx,wordseed ordx,dx jnz@f rdtsc movdx,ax @@ movax,wordseed2 orax,ax jnz@f inax,40h @@ muldx incax movwordseed,dx movwordseed2,ax xordx,dx subdi,si incdi divdi movax,dx addax,si popdi popdx popcx ret |
Функция принимает на входе в регистре минимальное число, а в регистре максимальное число диапазона, в котором генерируется случайное число (общий диапазон генерируемых значений: 0..65535). На выходе в регистре получаем псевдослучайное число. Генератор использует сразу две внутренние переменные, поэтому не забудьте их описать:
seed dw 0
seed2 dw 0
1 |
seeddw seed2dw |
Время как источник случайности
Если вы запустите предыдущую программу несколько раз, вы обнаружите проблему: числа будут те же самые. Причина проста — в начале последовательности мы используем всегда одно и то же число, 18. Для последовательности это число является зерном (англ. seed), и чтобы последовательность менялась с каждым запуском, зерно должно быть случайным.
Простейший, но не самый лучший способ получения зерна: взять текущее календарное время в секундах. Для этой цели мы воспользуемся функцией std::time_t time(std::time_t* arg).
Теперь программа при каждом запуске будет выводить разные цепочки псевдослучайных чисел. При условии, что вы запускаете её не чаще одного раза в секунду.
Игра в кости с использованием модуля random в Python
Далее представлен код простой игры в кости, которая поможет понять принцип работы функций модуля random. В игре два участника и два кубика.
- Участники по очереди бросают кубики, предварительно встряхнув их;
- Алгоритм высчитывает сумму значений кубиков каждого участника и добавляет полученный результат на доску с результатами;
- Участник, у которого в результате большее количество очков, выигрывает.
Код программы для игры в кости Python:
Python
import random
PlayerOne = «Анна»
PlayerTwo = «Алекс»
AnnaScore = 0
AlexScore = 0
# У каждого кубика шесть возможных значений
diceOne =
diceTwo =
def playDiceGame():
«»»Оба участника, Анна и Алекс, бросают кубик, используя метод shuffle»»»
for i in range(5):
#оба кубика встряхиваются 5 раз
random.shuffle(diceOne)
random.shuffle(diceTwo)
firstNumber = random.choice(diceOne) # использование метода choice для выбора случайного значения
SecondNumber = random.choice(diceTwo)
return firstNumber + SecondNumber
print(«Игра в кости использует модуль random\n»)
#Давайте сыграем в кости три раза
for i in range(3):
# определим, кто будет бросать кости первым
AlexTossNumber = random.randint(1, 100) # генерация случайного числа от 1 до 100, включая 100
AnnaTossNumber = random.randrange(1, 101, 1) # генерация случайного числа от 1 до 100, не включая 101
if( AlexTossNumber > AnnaTossNumber):
print(«Алекс выиграл жеребьевку.»)
AlexScore = playDiceGame()
AnnaScore = playDiceGame()
else:
print(«Анна выиграла жеребьевку.»)
AnnaScore = playDiceGame()
AlexScore = playDiceGame()
if(AlexScore > AnnaScore):
print («Алекс выиграл игру в кости. Финальный счет Алекса:», AlexScore, «Финальный счет Анны:», AnnaScore, «\n»)
else:
print(«Анна выиграла игру в кости. Финальный счет Анны:», AnnaScore, «Финальный счет Алекса:», AlexScore, «\n»)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
importrandom PlayerOne=»Анна» PlayerTwo=»Алекс» AnnaScore= AlexScore= diceOne=1,2,3,4,5,6 diceTwo=1,2,3,4,5,6 defplayDiceGame() «»»Оба участника, Анна и Алекс, бросают кубик, используя метод shuffle»»» foriinrange(5) #оба кубика встряхиваются 5 раз random.shuffle(diceOne) random.shuffle(diceTwo) firstNumber=random.choice(diceOne)# использование метода choice для выбора случайного значения SecondNumber=random.choice(diceTwo) returnfirstNumber+SecondNumber print(«Игра в кости использует модуль random\n») foriinrange(3) # определим, кто будет бросать кости первым AlexTossNumber=random.randint(1,100)# генерация случайного числа от 1 до 100, включая 100 AnnaTossNumber=random.randrange(1,101,1)# генерация случайного числа от 1 до 100, не включая 101 if(AlexTossNumber>AnnaTossNumber) print(«Алекс выиграл жеребьевку.») AlexScore=playDiceGame() AnnaScore=playDiceGame() else print(«Анна выиграла жеребьевку.») AnnaScore=playDiceGame() AlexScore=playDiceGame() if(AlexScore>AnnaScore) print(«Алекс выиграл игру в кости. Финальный счет Алекса:»,AlexScore,»Финальный счет Анны:»,AnnaScore,»\n») else print(«Анна выиграла игру в кости. Финальный счет Анны:»,AnnaScore,»Финальный счет Алекса:»,AlexScore,»\n») |
Вывод:
Shell
Игра в кости использует модуль random
Анна выиграла жеребьевку.
Анна выиграла игру в кости. Финальный счет Анны: 5 Финальный счет Алекса: 2
Анна выиграла жеребьевку.
Анна выиграла игру в кости. Финальный счет Анны: 10 Финальный счет Алекса: 2
Алекс выиграл жеребьевку.
Анна выиграла игру в кости. Финальный счет Анны: 10 Финальный счет Алекса: 8
1 2 3 4 5 6 7 8 9 10 |
Игравкостииспользуетмодульrandom Аннавыигралаигрувкости.ФинальныйсчетАнны5ФинальныйсчетАлекса2 Аннавыигралаигрувкости.ФинальныйсчетАнны10ФинальныйсчетАлекса2 Аннавыигралаигрувкости.ФинальныйсчетАнны10ФинальныйсчетАлекса8 |
Вот и все. Оставить комментарии можете в секции ниже.
Алгоритм перемешивания
Часто возникает задача расставить уже имеющийся набор значений в произвольном порядке. С этой целью также используется генератор псевдослучайных чисел. При этом создается массив и заполняется значениями.
Сама процедура перемешивания происходит следующим образом. Генерируется два значения индексов массива случайным образом, и значения элементов с полученными индексами меняются местами. Процедура повторяется не менее N раз, где N — количество элементов массива.
В качестве примера рассмотрим перемешивание 20 значений (от 1 до 20) и повторим процедуру 20 раз.Реализация на Си
123456789101112131415161718192021222324252627282930
#include <stdio.h>#include <stdlib.h>#include <time.h>#define SIZE 20int main() { int a; srand(time(NULL)); // Заполняем массив последовательными значениями от 1 до 20 for (int i = 0; i < SIZE; i++) { a = i + 1; printf(«%2d «, a); } for (int i = 0; i < SIZE; i++) { // Генерируем случайно два индекса элементов int ind1 = rand() % 20; int ind2 = rand() % 20; // и меняем местами элементы с этими индексами int temp = a; a = a; a = temp; } printf(«\n»); // Выводим получившийся массив for (int i = 0; i < SIZE; i++) printf(«%2d «, a); getchar(); return 0;}
Примеры использования модуля random.
Базовое применение модуля:
>>> import random # Случайное float: 0.0 <= x < 1.0 >>> random.random() # 0.37444887175646646 # Случайное float: 2.5 <= x < 10.0 >>> random.uniform(2.5, 10.0) # 3.1800146073117523 # Интервал между прибытием в среднем 5 секунд >>> random.expovariate(1 5) # 5.148957571865031 # Четное целое число от 0 до 100 включительно >>> random.randrange(10) # 7 # Even integer from 0 to 100 inclusive >>> random.randrange(, 101, 2) 26 # Один случайный элемент из последовательности >>> random.choice() 'draw' >>> deck = 'ace two three four'.split() # Перемешать список >>> random.shuffle(deck) >>> deck 'four', 'two', 'ace', 'three' # Четыре образца без замены >>> random.sample(, k=4) #
Имитационные расчеты:
# Шесть вращений колеса рулетки (взвешенная выборка с заменой) >>> choices(, 18, 18, 2], k=6) # # Сдайте 20 карт без замены из колоды из 52 игральных карт # и определите пропорцию карт с достоинством в: # десять, валет, дама или король. >>> dealt = sample(, counts=16, 36], k=20) >>> dealt.count('tens') 20 # 0.15 # Оценка вероятности получения 5 или более попаданий из 7 # бросаний монеты, которая выпадает орлом в 60% случаев. >>> def trial(): ... return choices('HT', cum_weights=(0.60, 1.00), k=7).count('H') >= 5 ... >>> sum(trial() for i in range(10_000)) 10_000 # 0.4169 >>> # Вероятность того, что медиана из 5 выборок находится в средних двух квартилях >>> def trial(): ... return 2_500 <= sorted(choices(range(10_000), k=5))[2 < 7_500 ... >>> sum(trial() for i in range(10_000)) 10_000 # 0.7958
Пример статистической начальной загрузки с использованием повторной выборки с заменой для оценки доверительного интервала для среднего значения выборки:
# http://statistics.about.com/od/Applications/a/Example-Of-Bootstrapping.htm from statistics import fmean as mean from random import choices data = 41, 50, 29, 37, 81, 30, 73, 63, 20, 35, 68, 22, 60, 31, 95 means = sorted(mean(choices(data, k=len(data))) for i in range(100)) print(f'The sample mean of {mean(data).1f} has a 90% confidence ' f'interval from {means5.1f} to {means94.1f}')
Пример теста перестановки повторной выборки для определения статистической значимости или Р-значения наблюдаемой разницы между эффектами препарата и плацебо:
# Example from "Statistics is Easy" by Dennis Shasha and Manda Wilson from statistics import fmean as mean from random import shuffle drug = 54, 73, 53, 70, 73, 68, 52, 65, 65 placebo = 54, 51, 58, 44, 55, 52, 42, 47, 58, 46 observed_diff = mean(drug) - mean(placebo) n = 10_000 count = combined = drug + placebo for i in range(n): shuffle(combined) new_diff = mean(combined) - mean(combinedlen(drug):]) count += (new_diff >= observed_diff) print(f'{n} label reshufflings produced only {count} instances with a difference') print(f'at least as extreme as the observed difference of {observed_diff.1f}.') print(f'The one-sided p-value of {count n.4f} leads us to reject the null') print(f'hypothesis that there is no difference between the drug and the placebo.')
Моделирование времени прибытия и доставки услуг для многосерверной очереди:
from heapq import heappush, heappop from random import expovariate, gauss from statistics import mean, median, stdev average_arrival_interval = 5.6 average_service_time = 15.0 stdev_service_time = 3.5 num_servers = 3 waits = [] arrival_time = 0.0 servers = 0.0 * num_servers # time when each server becomes available for i in range(100_000): arrival_time += expovariate(1.0 average_arrival_interval) next_server_available = heappop(servers) wait = max(0.0, next_server_available - arrival_time) waits.append(wait) service_duration = gauss(average_service_time, stdev_service_time) service_completed = arrival_time + wait + service_duration heappush(servers, service_completed) print(f'Mean wait: {mean(waits).1f}. Stdev wait: {stdev(waits).1f}.') print(f'Median wait: {median(waits).1f}. Max wait: {max(waits).1f}.')