Книга: Linux программирование в примерах
12.6.2. Функции POSIX: random() и srandom()
12.6.2. Функции POSIX: random()
и srandom()
BSD 4.3 ввело random() и сопровождающие ее функции. Эти функции используют намного более подходящий генератор случайных чисел, который возвращает 31-разрядное значение. Теперь они входят в расширение XSI, стандартизованное POSIX:
#include <stdlib.h> /* XSI */
long random(void);
void srandom(unsigned int seed);
char *initstate(unsigned int seed, char *state, size_t n);
char *setstate(char *state);
Первые две функции близко соответствуют rand()
и srand()
и могут использоваться сходным образом. Однако, вместо одного начального значения, которое дает последовательность псевдослучайных чисел, эти функции используют начальное значение вместе с массивом состояния: массивом байтов, который хранит сведения о состоянии для вычисления псевдослучайных чисел. Последние две функции дают возможность управлять массивом состояния.
long random(void);
Возвращает число в диапазоне от 0 до 231-1. (Хотя справочная страница GNU/Linux random(3) говорит между 0 и RAND_MAX
, это верно лишь для систем GLIBC, где RAND_MAX
равен 231-1. На других системах RAND_MAX
может быть меньше. POSIX явно называет диапазон от 0 до 231-1.)
void srandom(unsigned int seed);
Устанавливает начальное число. Если srandom()
никогда не вызывается, по умолчанию используется 1.
char *initstate(unsigned int seed, char *state, size_t n);
Инициализирует массив state
информацией для использования при генерации случайных чисел, seed
является начальным значением, как для srandom()
, а n является числом байтов в массиве state
.
n должен равняться одному из значений 8, 32, 64, 128 или 256. Большие значения дают лучшие последовательности случайных чисел. Значения меньше 8 заставляют random()
использовать простой генератор случайных чисел, сходный с rand()
. Значения больше 8, не равные одному из значений в списке, округляются до ближайшего подходящего значения.
char *setstate(char *state);
Устанавливает внутреннее состояние в соответствии с массивом state
, который должен быть инициализирован посредством initstate()
. Это позволяет переключаться по желанию между различными состояниями, предоставляя множество генераторов случайных чисел.
Если initstate()
и setstate()
никогда не вызывались, random()
использует массив внутреннего состояния размером 128.
Массив state
непрозрачен; вы инициализируете его с помощью initstate()
и передается функции random()
посредством setstate()
, но в другом отношении вам не нужно заглядывать в него. Если вы используете initstate()
и setstate()
. srandom()
вызывать не нужно, поскольку начальное значение включено в информацию о состоянии. ch12-random.c
использует эти процедуры вместо rand()
. Используется также обычная методика, которая заключается в использовании в качестве начального значения генератора случайных чисел времени дня, добавленного к PID.
1 /* ch12-random.c --- генерация вращения костей с использованием random(). */
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <sys/types.h>
6 #include <unistd.h>
7
8 char *die_faces[] = { /* Управляет ASCII графика! */
/* ... как раньше ... */
32 };
33
34 /* main --- выводит N различных граней кубиков */
35
36 int main(int argc, char **argv)
37 {
38 int nfaces;
39 int i, j, k;
40 char state[256];
41 time_t now;
42
/* ... проверка args, вычисление nfaces, как раньше ... */
55
56 (void)time(&now); /* В качестве начального значения используются время дня и PID */
57 (void) initstate((unsigned int)(now + getpid()), state, sizeof state);
58 (void)setstate(state);
59
60 for (i = 1; i <= nfaces; i++) {
61 j = random() % 6; /* использовать диапазон 0 <= j <= 5 */
62 printf("+-------+n");
63 for (k = 0; k < 3; k++)
64 printf("|%s|n", die_faces[(j * 3) + k]);
65 printf("+-------+nn");
66 }
67
68 return 0;
69 }
Включение PID в состав начального значения гарантирует, что вы получите различные результаты, даже если две программы будут запушены в течение одной и той же секунды.
Поскольку она создает последовательности случайных чисел лучшего качества, random()
является более предпочтительной по сравнению с rand()
, и GNU/Linux и все современные системы Unix ее поддерживают.
- 14.2.2. Блокировка POSIX: fcntl() и lockf()
- 10.6. Сигналы POSIX
- Глава 12 Потоки POSIX
- POSIX IPC Awareness
- Семантика сигналов POSIX
- Аргументы функции в Python
- 3. Функции
- Новые функции API для работы с Blob и массивами
- Математические функции
- Размытые функции
- 7.3. Финансовые функции
- 4.3. Логические функции и таблицы истинности