Случайные числа в языке программирования С++ могут быть сгенерированы функцией rand()
из стандартной библиотеки С++. Функция rand()
генерирует числа в диапазоне от 0 до RAND_MAX
. RAND_MAX
— это константа, определённая в библиотеке <cstdlib>
. Для MVS RAND_MAX
= 32767, но оно может быть и больше, в зависимости от компилятора. Ниже показана простая программка, использующая генератор случайных чисел rand()
(см. Рисунок 1).
// random.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include <iostream> using namespace std; int main(int argc, char* argv[]) { cout << "RAND_MAX = " << RAND_MAX << endl; // константа, хранящая максимальный предел из интервала случайных чисел cout << "random number = " << rand() << endl; // запуск генератора случайных чисел system("pause"); return 0; }
В строке 9 значение константы RAND_MAX
выталкивается в поток вывода, так мы сможем посмотреть максимальное значение из интервала случайных чисел. В строке 10 запускается генератор случайных чисел rand()
, причём он сгенерирует случайное число один раз, при первом запуске программы. В дальнейшем, сколько бы Вы не запускали эту программу, сгенерированное число останется одним и тем же.
Рисунок 1 — Генератор случайных чисел rand()
Как видно из рисунка 1 максимальное случайное число — это 32767. Функция rand()
сгенерировала число 41. Зачастую, нам не нужен такой большой диапазон чисел от 0 до RAND_MAX
. Например, в игре «Наперстки» необходимо отгадать, под каким из трёх напёрстков спрятан шарик, то есть генерация чисел должна выполняться в пределе от 1 до 3-х. Бросая монету, может возникнуть только два случая, когда монета упадёт «орлом» или «решкой» вверх, нужный интервал — от 1 до 2. Возникает потребность в масштабировании интервала генерации случайных чисел. Для того чтобы масштабировать интервал генерации чисел нужно воспользоваться, операцией нахождения остатка от деления «%«.
// пример масштабирования диапазона генерации случайных чисел rand() % 3 +1 // диапазон равен от 1 до 3 включительно
Число 3 является масштабируемым коэффициентом. То есть, какое бы не выдал число генератор случайных чисел rand()
запись rand() % 3
в итоге выдаст число из диапазона от 0 до 2. Для того чтобы сместить диапазон, мы прибавляем единицу, тогда диапазон изменится на такой — от 1 до 3 включительно.
// формула генерации случайных чисел по заданному диапазону random_number = firs_value + rand() % last_value; // где firs_value - минимальное число из желаемого диапазона // last_value - ширина выборки
Разработаем программу, использующую масштабируемый генератор случайных чисел. Ниже показан код программы, которая несколько раз запускает функцию rand()
.
// rand_ost.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include <iostream> using namespace std; int main(int argc, char* argv[]) { cout << "1-random number = " << 1 + rand() % 3 << endl; // первый запуск генератора случайных чисел cout << "2-random number = " << 1 + rand() % 3 << endl; // второй запуск генератора случайных чисел cout << "3-random number = " << 1 + rand() % 3 << endl; // третий запуск генератора случайных чисел cout << "4-random number = " << 1 + rand() % 3 << endl; // четвёртый запуск генератора случайных чисел cout << "5-random number = " << 1 + rand() % 3 << endl; // пятый запуск генератора случайных чисел cout << "6-random number = " << 1 + rand() % 3 << endl; // шестой запуск генератора случайных чисел cout << "7-random number = " << 1 + rand() % 3 << endl; // седьмой запуск генератора случайных чисел cout << "8-random number = " << 1 + rand() % 3 << endl; // восьмой запуск генератора случайных чисел system("pause"); return 0; }
Начиная с 9-й по 16-ю строки, включительно, выполняется запуск генератора случайных чисел rand()
. В данной программе 8 раз был запущен генератор случайных чисел rand()
с целью выявления случайности срабатывания. Функция rand()
выполняется с масштабированием, причём минимальное число из желаемого диапазона равно единице, а ширина выборки равна 3-м. Таким образом, наш диапазон от 1 до 3, включительно. Результат работы программы (см. Рисунок 2).
Рисунок 2 — Генератор случайных чисел rand()
Из рисунка 2 видно, что генератор случайных чисел rand()
был запущен 8 раз. Из восьми раз:
- тройка показалась три раза, P = 3/8 = 0.375 — вероятность появления тройки
- двойка показалась три раза, P = 3/8 = 0.375 — вероятность появления двойки
- единица показалась два раза, P = 2/8 = 0.25 — вероятность появления единицы
Все эти вероятности приблизительны, так как испытание проводилось только 8 раз, если вы попробуете у себя скомпилить данный код, то результат может получиться совсем другой.
При повторном запуске программы, печатаются те же самые числа. Суть в том, что функция rand()
один раз генерирует случайные числа, а при последующих запусках программы всего лишь отображает сгенерированные первый раз числа. Такая особенность функции rand()
нужна для того, чтобы можно было правильно отладить разрабатываемую программу. При отладке программы, внеся какие-то изменения, необходимо удостовериться, что программа срабатывает правильно, а это возможно, если входные данные остались те же, то есть сгенерированные числа. Когда программа успешно отлажена, нужно, чтобы при каждом выполнении программы генерировались случайные числа. Для этого нужно воспользоваться функцией srand()
из стандартной библиотеки С++. Функция srand()
получив целый положительный аргумент типа unsigned
или unsigned int
(без знаковое целое) выполняет рандомизацию, таким образом, чтобы при каждом запуске программы функция srand()
генерировала случайные числа. Программа, использующая функцию srand()
для рандомизации генератора случайных чисел rand()
(см. Рисунок 3).
// srand.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include <iostream> using namespace std; int main(int argc, char* argv[]) { unsigned rand_value = 11; srand(rand_value); // рандомизация генератора случайных чисел cout << "rand_value = " << rand_value << endl; cout << "1-random number = " << 1 + rand() % 10 << endl; // первый запуск генератора случайных чисел cout << "2-random number = " << 1 + rand() % 10 << endl; // второй запуск генератора случайных чисел system("pause"); return 0; }
В строке 10 выполняется функция srand()
, которая принимает в качестве аргумента целое положительное число 11. При первом запуске мы получили случайные числа, и при последующих запусках программы мы видим всё те же числа. Так вот, чтоб каждый раз генерировались новые случайные числа необходимо, что бы менялся аргумент в функции srand()
. На следующих рисунках наглядно можно посмотреть как меняются сгенерированные числа, относительно изменяющегося значения в переменной rand_value
(см. Рисунки 3 и 4 ).
Рисунок 3 — Генератор случайных чисел rand()
Рисунок 4 — Генератор случайных чисел rand()
Из рисунков 3 и 4 видно, что при изменении значения rand_value
меняются числа, причём в первом и во втором запусках функции rand()
. То, что на рисунке 4 в первом случае осталось такое же случайное число — это совпадение.
И наконец, чтобы производить рандомизацию автоматически, то есть, не меняя каждый раз аргумент в функции srand()
нужно воспользоваться функцией time()
с аргументом 0.
// автоматическая рандомизация srand( time(0) );
Чтобы использовать функцию time()
, необходимо подключить заголовочный файл <ctime>
.
Разработаем обобщённый пример использования автоматического генератора случайных чисел с масштабированием. Пример работы программы (см. Рисунок 5).
// srand_time.cpp: определяет точку входа для консольного приложения. #include "stdafx.h" #include <iostream> #include <ctime> using namespace std; int main(int argc, char* argv[]) { srand( time( 0 ) ); // автоматическая рандомизация cout << "rand_value = " << 1 + rand() % 10 << endl; system("pause"); return 0; }
Теперь при каждом срабатывании программы будут генерироваться совершенно случайные числа в интервале от 1 до 10, включительно (см. Рисунок 5).
Рисунок 5 — Генератор случайных чисел rand()
Комментарии
Илья Самойленко
хах, а зачем тогда rand, если time прекрасно справляется с задачей)))
Илья Самойленко
чтобы тестить только получается))
Denis Makarov
ой ой ой
Makswell
чето ваш генератор одни и теже числа постоянно выдаёт)))))
Первое всегда 41, второе 18467, третье 5334 и т. д.
Это не генератор случайных чисел а их последовательность…..
Makswell
нужно было статью сначала дочитать)))
PayL
Начиная с этой статьи, и в следующих, не хватает в программах строчки #include <cstdlib>. Без неё у меня в CodeBlocks не запускается ни одна прога, где присутствует команда rand. Хорошо что в описании написано об этой библиотеке, ато вабче была бы беда.
Дмитрий Петров
Хороший вопрос выше. Тоже интересен ответ)
lfenix
А равномерно будут распределенны значения, полученные с помощью
rand() % x
? Просто если значение RAND_MAX, для примера, равно 100, а x = 80, не получится ли, что числа от 0 до 20 будут появляться в 2 раза чаше других?