Самый простой вариант задания диапазаноа для функции rand():
n = а + rand() % b;
a — величина сдвиг, которая равна первому числу в требуемом диапазоне последовательности целых чисел. b — масштабируемый коэффициент, который равен ширине требуемого диапазона целых чесиел.
Пример: требутся сгенерировать случайные числа в диапазоне от 1 до 6:
n = 1 + rand() % 6;
Этот способ описан в книге Харви и Пола Дейтелов "Как программировать на С++".
Однако, тут имеется одно НО: функция rand() — это генератор ПСЕВДОСЛУЧАЙНЫХ чисел с "затравкой", который генерирует последовательность чисел длиной М, в зависимости от затравки.
Особенности таких генераторов:
1. Генератор повторяется, через период, равный М (от этого никуда не деться).
2. Генератор выдаёт одну и ту же последовательность, в зависимости от "затравки", которая устанавливается функцией srand(unsigned int seed). Т.е. для одной затравки rand()
генерирует всегда одну и ту же последовательность(и от этого тоже).
Эти особенности надо учитывать. Таким образом, если в разных объектах одного класса требуется генерировать независимые друг от друга последовательности функция rand() не подходит, потому что оба класса будут получать числа из одной и той же последовательности, длинной М. Если оба объекта будут вызывать rand() одинаковое количество раз, то они получат M/2 чисел, потом генератор начнёт повторяться (соответственно 3 объекта = M/3 чисел, и т.д.)
Вызывать в конструкторе каждый раз функцию srand() нет смысла, т.к. она конечно же поменяет затравку, но опять-таки все объекты будут использовать одну затравку для генерации псевдослучайных чисел. А каждый раз вызывать srand() перед вызовом ранд — не эффективно, да и затравку надо где взять. Использовать время?
srand( static_cast<unsigned int> time( NULL ) );
x = rand();
Однако функция time() вызвращает время в секундах, сколько миллионов раз вызовется rand() за 1 секунду? Если учесть, что для одной затравки генерируется одна последовательность ПСЧ, то в течение 1 секунды rand() будет возвращать 1 и то же число. То же самое справедливо и для реализаций time(), которые возвращают миллисекунды.
Как вариант можно написать свое генератор псевдослучайных чисел (ПСЧ). Это хорошо описано Д. Кнутом "Искуство программирования", том 2, раздел 3.2 "Генерирование равномерно распределённых случайных чисел".
В кратце там написано следующее:
Одним из хороших конгруэнтных генераторов является линейный конгруэнтный датчик ПСЧ. Он вырабатывает последовательности псевдослучайных чисел T(i), описываемые соотношением
T( i+1) = ( A * T( i ) + C ) % M
A и C — константы. T(0) — исходная величина, выбранная в качестве порождающего числа (затравка).
Как показано Д.Кнуттом, линейный конгруэнтный датчик имеет максималь-ную длину M тогда, когда C нечетное и A mod 4 = 1.
Для чего нужно реализовывать вроде бы такой же, как и rand() генератор ПСЧ? Для того, чтобы получить возможность задавать в каждом конкретном объекте класса свою затравку, и получать последовательность ПСЧ длинной М, независимо, от количества созданных объектов. А затравку для нашего генератора ПСЧ можно задаваться с помощью rand().
Здравствуйте, Erlond, Вы писали:
E>Как вариант можно написать свое генератор псевдослучайных чисел (ПСЧ). Это хорошо описано Д. Кнутом "Искуство программирования", том 2, раздел 3.2 "Генерирование равномерно распределённых случайных чисел".
Можно ещё посмотреть в сторону функции CryptGenRandom, если на win сидите.