Как работает rand c
Перейти к содержимому

Как работает rand c

  • автор:

Прототип функции rand:

Функция rand генерирует случайные числа, возвращает псевдослучайное целое число в диапазоне от 0 до RAND_MAX .

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

RAND_MAX это константа, определенная в . По умолчанию её значение может изменяться, в зависимости от реализации, но, как правило, макрос RAND_MAX меньше значения 32767 не бывает.

Типичный способ генерации псевдослучайных чисел в определенном диапазоне с использованием функции rand выполняется следующим образом:

(value % 100) — генерация чисел в диапазоне от 0 до 99
(value % 100 + 1) — генерация чисел в диапазоне от 1 до 100
(value % 30 + 1985) — генерация чисел в диапазоне от 1985 до 2014

Однако, использование операции остаток от деления не создает поистине равномерно распределенных случайных чисел в заданном диапазоне, но, как правило, такой способ генерации чисел является хорошим приближением для небольших диапазонов.

Параметры:

Функция не принимает аргументов.

Возвращаемое значение

Целое псевдослучайное число в диапазоне от 0 до RAND_MAX .

Пример: исходный код программы

//пример использования функции rand #include #include #include int main () < int guess; srand ( time(NULL) ); // инициализация функции rand значением функции time int secret = rand() % 10 + 1; // сгенерировать секретное число do < std::cout > guess; if (secret < guess) std::cout guess) std::cout while (secret != guess); std::cout

Пример работы программы

CppStudio.com

Отгадайте число (от 1 до 10): 4
Секретное число меньше
Отгадайте число (от 1 до 10): 2
Мои поздравления.

В этом примере, случайное зерно генерируется функцией time (функция time определена в заголовке ). Использование данной функции — простой и достаточно хороший вариант генерации зерна.

Что такое rand в C++?

Для генерации случайных чисел необходимо использовать метод rand() . Чтобы создать случайное число в диапазоне от 1 до 20 потребуется следующий код:

int num = 1 + rand() % 20;

Кроме того, у вас могут возникать проблемы с тем, что постоянно выводиться одно и тоже самое число. Чтобы такого не было подключите библиотеку #include и в функции main первой строкой пропишите srand(time(NULL)); .

#include #include using namespace std; int main() < setlocale(LC_ALL, "Russian"); // Русская локализация консоли srand(time(NULL)); // Генерирует случайное число, используя текущую дату как параметр cout

Для работы со строками необходимо подключить библиотеку #include . Чтобы получить целую строку введенную с клавиатуры используйте функцию getline(cin, value). Здесь value это переменная, в которую будет записано значение, полученное от пользователя.

rand

Создает псевдослучайное число. Доступна более программно безопасная версия этой функции; см. раздел rand_s . Числа, созданные rand не криптографически безопасными. Для более криптографически безопасного создания случайных чисел используйте rand_s или функции, объявленные в стандартной библиотеке C++ в .

Синтаксис

int rand(void); 

Возвращаемое значение

Функция rand возвращает псевдослучайное число, как описано выше. Не возвращается ошибка.

Замечания

Функция rand возвращает псевдослучайное целое число в диапазоне от 0 до RAND_MAX (32767). Используйте функцию srand для заполнения генератора псевдорандомных чисел перед вызовом rand .

Функция rand создает известную последовательность и не подходит для использования в качестве криптографической функции. Для более криптографически безопасного создания случайных чисел используйте rand_s или функции, объявленные в стандартной библиотеке C++ в .

По умолчанию глобальное состояние этой функции ограничивается приложением. Чтобы изменить это поведение, см . статью "Глобальное состояние" в CRT.

Требования

Маршрут Обязательный заголовок
rand

Дополнительные сведения о совместимости см. в разделе Совместимость.

Пример

// crt_rand.c // This program seeds the random-number generator // with a fixed seed, then exercises the rand function // to demonstrate generating random numbers, and // random numbers in a specified range. #include // rand(), srand() #include // printf() void SimpleRandDemo(int n) < // Print n random numbers. for (int i = 0; i < n; i++) < printf(" %6d\n", rand()); >> void RangedRandDemo(int range_min, int range_max, int n) < // Generate random numbers in the interval [range_min, range_max], inclusive. for (int i = 0; i < n; i++) < // Note: This method of generating random numbers in a range isn't suitable for // applications that require high quality random numbers. // rand() has a small output range [0,32767], making it unsuitable for // generating random numbers across a large range using the method below. // The approach below also may result in a non-uniform distribution. // More robust random number functionality is available in the C++ header. // See https://learn.microsoft.com/cpp/standard-library/random int r = ((double)rand() / RAND_MAX) * (range_max - range_min) + range_min; printf(" %6d\n", r); > > int main(void) < // Seed the random-number generator with a fixed seed so that // the numbers will be the same every time we run. srand(1792); printf("Simple random number demo ====\n\n"); SimpleRandDemo(10); printf("\nRandom number in a range demo ====\n\n"); RangedRandDemo(-100, 100, 100000); >``` ```Output Simple random number demo ==== 5890 1279 19497 1207 11420 3377 15317 29489 9716 23323 Random number in a range demo ==== -82 -46 50 77 -47 32 76 -13 -58 90 

Случайные числа в языке C

В языках программирования обычно предусмотрены функции, позволяющие генерировать случайные числа в определенном по умолчанию диапазоне. На самом деле генерируются не случайные, а так называемые псевдослучайные числа; они выглядят случайно, но вычисляются по вполне конкретной формуле. Далее для простоты мы все равно будем называть их случайными.

В языке программирования C получить случайное число можно с помощью функции rand() , которая входит в стандартную библиотеку языка. Эта функция не принимает никакие параметры.

#include #include int main() { int a = rand(); printf("%d\n", a); }

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

int a = RAND_MAX; printf("%d\n", a); // 2147483647

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

for (int i = 1; i  50; i++) { printf("%15d", rand()); if (i % 5 == 0) printf("\n"); }

В теле цикла осуществляется переход на новую строку после каждых выведенных на экран пяти чисел. Для этого используется выражение, в котором находится остаток от деления i на 5, результат сравнивается с 0. Чтобы после первого числа не происходил переход на новую строку, i сначала присваивается единица, а не ноль (т.к. 0 делится на 5 без остатка).

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

Инициирующее значение можно запрашивать у пользователя с помощью scanf() и передавать его в srand() .

scanf("%d", &n); srand(n);

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

Текущее время можно узнать с помощью функции time() , прототип которой описан в файле time.h. Передав time() в качестве параметра NULL , мы получим целое число, которое можно передать в srand() :

srand(time(NULL));

Получение целых случайных чисел в заданных диапазонах

Функция rand() выдает случайное число от 0 до значения RAND_MAX . Что делать, если требуется получать случайные числа в иных диапазонах, например, от 100 до 999?

Сначала рассмотрим более простую ситуацию: получить случайные числа от 0 до 5. Если любое целое число попытаться разделить на 5 нацело, то в качестве остатка можно получить как 0 (когда число делится на 5 без остатка), так и 1, 2, 3, 4. Например, rand() вернула число 283. Применяя к этому числу операцию нахождения остатка от деления на 5, получим 3. Т.е. выражение rand() % 5 дает любое число в диапазоне [0, 5).

Однако, что если надо, чтобы число 5 так же входило в диапазон, т.е. диапазон имеет вид [0, 5]? Логично предположить, что следует найти остаток от деления на 6. При этом более грамотным будет следующее рассуждение: надо находить остаток от деления на размер диапазона. В данном случае он равен шести значениям: 0, 1, 2, 3, 4, 5. Чтобы найти размер диапазона, надо из допустимого максимума вычесть допустимый минимум и прибавить единицу: max - min + 1. Будьте внимательны: если, например, требуется, чтобы указанный в задаче максимум не входил в диапазон, то единицу прибавлять не надо или надо вычитать единицу из максимума.

Следующее выражение выведет на экране случайное число от 0 до 99 включительно:

printf("%d\n", rand() % 100);

Итак, мы знаем формулу получения длины диапазона: max - min + 1. Если требуется получить число от 6 до 10 включительно, то длина диапазона будет равна 10 - 6 + 1 = 5. Выражение rand()% 5 даст любое число от 0 до 4 включительно. Но нам надо от 6 до 10. В таком случае достаточно к полученному случайному остатку прибавить 6, т.е. минимум. Другими словами, надо выполнить сдвиг. Действительно, для приведенного примера:

  • если остаток был равен 0, то добавляя 6, получаем 6;
  • остаток 1, добавляем 6, получаем 7;
  • остаток 4, прибавляем 6, получаем 10;
  • остатка больше 4 не может быть.

В таком случае формула для получения случайного числа в диапазоне [a, b] выглядит так:

rand() % длина_диапазона + сдвиг

где длина_диапазона вычисляется как b - a + 1, сдвиг является значением a .

В эту формулу также вписываются случаи, когда необходимо получить случайное число от 0 до N, т.е. они являются ее частными случаями.

Выведите на экран ряд случайных чисел, принадлежащих диапазону от 100 до 299 включительно.

С таким же успехом можно получать случайные отрицательные числа. Если диапазон задан как [-35, -1], то его длина будет равна -1 - (-35) + 1 = 35, что соответствует действительности; выражение получения случайного числа будет выглядеть так:

rand() % 35 - 35 

Так, если остаток от деления составил 0, то мы получим -35, а если 34, то -1. Остальные остатки дадут значения в промежутке от -35 до -1.

Выведите на экран ряд случайных чисел, принадлежащих диапазону от -128 до 127 включительно.

Получение вещественных случайных чисел

Ситуация с вещественными числами выглядит несколько по-иному. Во-первых, мы не можем получить остаток от деления, если делимое или делитель дробные числа. Во вторых при вычислении длины диапазона нельзя прибавлять единицу.

Поясним вторую причину. Допустим диапазон задан как [2.50, 5.30]. Он состоит не из определенного количества чисел (как в случае целых), а из неопределенного (можно сказать, бесконечного) числа значений, т.к. вещественные числа можно представлять с различной степенью точности. Позже выполняя округление все равно будет шанс получить максимальную границу диапазона, поэтому для вычисления длины диапазона достаточно из максимума вычесть минимум.

Если разделить случайное число, преобразованное к вещественному типу, которое выдала функция rand() , на значение константы RAND_MAX , то получится вещественное случайное число от 0 до 1. Теперь, если это число умножить на длину диапазона, то получится число, лежащее в диапазоне от 0 до значения длины диапазона. Далее если прибавить к нему смещение к минимальной границе, то число благополучно впишется в требуемый диапазон. Таким образом формула для получения случайного вещественного числа выглядит так:

(float) rand() / RAND_MAX * (max - min) + min

Заполните массив случайными числами в диапазоне от 0.51 до 1.00. Выведите значение элементов массива на экран.

Равновероятные случайные числа

Функция rand() генерирует любое случайное число от 0 до RAND_MAX с равной долей вероятности. Другими словами, у числа 100 есть такой же шанс выпасть, как и у числа 25876.

Чтобы доказать это, напишем программу, подсчитывающую количество выпадений каждого из значений. Если выборка (количество "испытуемых") будет достаточно большой, а диапазон (разброс значений) маленьким, то мы должны увидеть, что процент выпадений того или иного значения приблизительно такой же как у других.

#include #include #define N 500 int main () { int i; int arr[5] = {0}; srand(time(NULL)); for (i=0; i  N; i++) switch (rand() % 5) { case 0: arr[0]++; break; case 1: arr[1]++; break; case 2: arr[2]++; break; case 3: arr[3]++; break; case 4: arr[4]++; break; } for (i=0; i  5; i++) printf("%d - %.2f%%\n", i, ((float) arr[i] / N) * 100); }

В приведенной программе массив из пяти элементов сначала заполняется нулями. Случайные числа генерируются от 0 до 4 включительно. Если выпадает число 0, то увеличивается значение первого элемента массива, если число 1, то второго, и т.д. В конце на экран выводится процент выпадения каждого из чисел.

Чем больше значение константы N, тем меньше будут отличаться между собой проценты выпадения каждого из чисел.

Курс с решением задач:
pdf-версия

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *