Генерация (псевдо) случайных чисел в языке СИ

Содержание

Слайд 2

Случайные числа. Генераторы случайных чисел Современные компиляторы обладают собственной реализацией генератора

Случайные числа. Генераторы случайных чисел

Современные компиляторы обладают собственной реализацией генератора псевдослучайных

последовательностей.
Основная сложность генерации последовательности псевдослучайных чисел на компьютере в том, что компьютеры детерминированы по своей сути. Компьютер может находиться только в конечном количестве состояний (количество состояний огромно, но все-таки конечно). Следовательно любой датчик случайных чисел по определению периодичен. Все периодическое – предсказуемо, т.е. не случайно.
Слайд 3

Генераторы случайных чисел С криптографической точки зрения они являются непригодными. Лучшее,

Генераторы случайных чисел

С криптографической точки зрения они являются непригодными.
Лучшее, что может

произвести компьютер – это псевдослучайная последовательность.
Период такой последовательности должен быть таким, чтобы конечная последовательность разумной длины не была периодической. Относительно короткие непериодические подпоследовательности должны быть как можно более неотличимы от
случайных последовательностей, в частности, соответствовать различным критериям
случайности.
Слайд 4

Генераторы случайных чисел Генератор последовательности называется случайным, если он не может

Генераторы случайных чисел

Генератор последовательности называется случайным, если он не может быть

достоверно воспроизведен, т.е. дважды запуская генератор с абсолютно одинаковыми
исходными данными (по крайней мере, на пределе возможностей), мы получим случайные различные последовательности.
Генератор псевдослучайной последовательности
выдает поток битов, который выглядит случайными, но в действительности является
детерминированным и может быть в точности воспроизведен.
Слайд 5

Линейный конгруэнтный генератор псевдослучайных чисел Линейный конгруэнтный генератор (ЛКГ) – это

Линейный конгруэнтный генератор псевдослучайных чисел

Линейный конгруэнтный генератор (ЛКГ) – это последовательность

чисел от 0 до m −1, удовлетворяющая следующему рекуррентному выражению - начальное значение, a – множитель, b – приращение, m – модуль. У такого генератора период меньше m . Если a , b , m правильно выбраны, то генератор является генератором максимальной длины и имеет период m.
Слайд 6

Линейный конгруэнтный генератор псевдослучайных чисел Если инкремент b равен нулю, то

Линейный конгруэнтный генератор псевдослучайных чисел

Если инкремент b равен нулю, то есть

генератор имеет вид:
получим самую простую последовательность, которую можно предложить для генератора с равномерным распределением. При соответствующем выборе констант a может принимать значения 75 либо 16 807 и m принимать значения
2 147 483 647 получим генератор с максимальным периодом повторения. Эти константы были предложены учеными Парком и Миллером, поэтому генератор вида:
называется генератором Парка-Миллера.
Слайд 7

Линейный конгруэнтный генератор псевдослучайных чисел Реализация генератора Парка-Миллера.

Линейный конгруэнтный генератор псевдослучайных чисел

Реализация генератора Парка-Миллера.

Слайд 8

Псевдослучайные числа в СИ Функция, генерирующая псевдослучайные числа, имеет прототип в

Псевдослучайные числа в СИ

Функция, генерирующая псевдослучайные числа, имеет прототип в файле

библиотеки stdlib.h
В этой библиотеке содержится функция rand(), которая и генерирует случайное число. Эта функция не принимает никакие параметры.
Функция rand() возвращает целое число от 0 до значения присвоенного константе RAND_MAX. Значение RAND_MAX зависит от системы и определено в заголовочном файле stdlib.h. Так, например, оно может быть равно 32767 (двухбайтовое целое) или 2147483647 (четырехбайтовое целое).
Слайд 9

Псевдослучайные числа в СИ Функция, генерирующая псевдослучайные числа, имеет прототип в

Псевдослучайные числа в СИ

Функция, генерирующая псевдослучайные числа, имеет прототип в файле

библиотеки stdlib.h
В этой библиотеке содержится функция rand(), которая и генерирует случайное число. Эта функция не принимает никакие параметры.
Функция rand() возвращает целое число от 0 до значения присвоенного константе RAND_MAX. Значение RAND_MAX зависит от системы и определено в заголовочном файле stdlib.h. Так, например, оно может быть равно 32767 (двухбайтовое целое) или 2147483647 (четырехбайтовое целое).
Слайд 10

Псевдослучайные числа в СИ Значение RAND_MAX равно 32767 (двухбайтовое целое).

Псевдослучайные числа в СИ

Значение RAND_MAX равно 32767 (двухбайтовое целое).

Слайд 11

Псевдослучайные числа в СИ Код ниже выводит на экран 25 случайных

Псевдослучайные числа в СИ

Код ниже выводит на экран 25 случайных чисел.

В теле цикла осуществляется переход на новую строку после каждых выведенных на экран пяти чисел.
Слайд 12

Псевдослучайные числа в СИ Для этого используется выражение, в котором находится

Псевдослучайные числа в СИ

Для этого используется выражение, в котором находится остаток

от деления i на 5, результат сравнивается с 0. Чтобы после первого числа не происходил переход на новую строку, i сначала присваивается единица, а не ноль (т.к. 0 делится на 5 без остатка).
Слайд 13

Функция rand При каждом запуске программы числа остаются одинаковыми. Даже если

Функция rand

При каждом запуске программы числа остаются одинаковыми. Даже если перекомпилировать

программу, результат не изменится. Данный эффект связан с тем, что начальное (инициализирующее) число, которое подставляется в формулу вычисления первого и последующих псевдослучайных чисел, для каждой системы всегда одно и то же.
Слайд 14

Функция srand Однако это начальное число можно изменить с помощью функции

Функция srand

Однако это начальное число можно изменить с помощью функции srand(),

которой в качестве параметра передается любое целое число.
Если вы зададите конкретный аргумент для функции, например, srand(1000), то от вызова к вызову программы числа будут также одни и те же. Хотя и не те, что были бы без srand(). Поэтому появляется проблема, как сделать так, чтобы аргумент для srand() был тоже случайным?
Слайд 15

Функция srand Пользователь программы сам может задавать инициализирующее значение. Но чаще

Функция srand

Пользователь программы сам может задавать инициализирующее значение. Но чаще всего

это не является полноценным выходом из ситуации. Поэтому инициализирующее значение привязывают к какому-либо процессу, протекающему в операционной системе, например, к часам. Время (учитывая не только время суток, но и дату) никогда не бывает одинаковым. Значит значение для srand(), преобразованное в целое из системного времени, будет различным.
Слайд 16

Функция srand Текущее время можно узнать с помощью функции time(), прототип

Функция srand

Текущее время можно узнать с помощью функции time(), прототип которой

описан в файле time.h.
Функция time в соответствии с системными часами возвращает количество секунд, прошедших от 00:00:00 значения времени по Гринвичу,т.е. с 1 января 1980 года (или 1970 года). Возвращаемое значение хранится в расположении, заданном по timeptr. Если возвращаемое значение не запомнилось, адрес timeptr является NULL.
Передав time() в качестве параметра NULL, мы получим целое число, которое можно передать в srand() : srand(time(NULL));
Слайд 17

Функция srand Код ниже выводит на экран 10 случайных чисел

Функция srand

Код ниже выводит на экран 10 случайных чисел

Слайд 18

Функция rand Функция возвращает случайное целое число в диапазоне от нуля

Функция rand

Функция возвращает случайное целое число в диапазоне от нуля до

RAND_MAX. Чтобы ограничить сверху случайные числа, можно воспользоваться операцией получения остатка от деления. Остаток от деления на числа K всегда меньше числа K. Например, при делении на 4 могут получиться остатки 0, 1, 2 и 3. Поэтому если вы хотите ограничить сверху случайные числа числом K, то можно взять остаток от деления на K.
Слайд 19

Функция rand Генерация пяти случайных целых чисел меньших K=10

Функция rand

Генерация пяти случайных целых чисел меньших K=10

Слайд 20

Функция rand В общем случае если нам нужно получить числа из

Функция rand

В общем случае если нам нужно получить числа из отрезка

[A;B], то можно воспользоваться следующей конструкцией: A + rand()%(B-A+1).
Например, необходимо получить случайные числа от 80 до 100.
Для этого используем выражение
80 + rand()%(100 - 80 + 1)
Слайд 21

Функция rand Пример программы генерирующей числа в диапазоне [80;100]

Функция rand

Пример программы генерирующей числа в диапазоне [80;100]

Слайд 22

Функция rand

Функция rand

Слайд 23

Функция rand Пример программы генерирующей числа в диапазоне [0;1]

Функция rand

Пример программы генерирующей числа в диапазоне [0;1]

Слайд 24

Комментарии к практической работе 4

Комментарии к практической работе 4