Чтение онлайн

на главную - закладки

Жанры

Linux программирование в примерах
Шрифт:

44 nfaces = atoi(argv[1]);

45

46 if (nfaces <= 0) {

47 fprintf(stderr, "usage: %s number-die-faces\n", argv[0]);

48 fprintf(stderr, "\tUse a positive number!\n");

49 exit(1);

50 }

51

52 for (i = 1; i <= nfaces; i++) {

53 j = rand % 6; /* force to range 0 <= j <= 5 */

54 printf("+-------+\n" );

55 for (k = 0; k < 3; k++)

56 printf("|%s|\n", die_faces[(j * 3) + k]);

57 printf ("+-------+\n\n");

58 }

59

60 return 0;

61 }

Эта программа использует простую ASCII-графику для распечатывания подобия грани игральной кости. Вы вызываете ее с числом граней для вывода. Это вычисляется в строке 44 с помощью

atoi
. (В общем,
atoi
следует избегать в коде изделия, поскольку она не осуществляет проверку на ошибки или переполнение, также как не проверяет вводимые данные.)

Ключевой является строка 53, которая преобразует возвращаемое значение

rand
в число от нуля до пяти, используя оператор остатка,
%
. Значение '
j * 3
' действует в качестве начального индекса массива
die_faces
для трех строк, составляющих каждую грань кости. Строки 55 и 56 выводят саму грань. При запуске появляется вывод наподобие этого:

$ ch12-rand 2 /* Вывести две кости */

+-------+

| |

| * * |

| |

+-------+

+-------+

| * * |

| * |

| * * |

+-------+

Интерфейс

rand
восходит еще к V7 и PDP-11. В частности, на многих системах результатом является лишь 16-разрядное число, что значительно ограничивает диапазон чисел, которые могут быть возвращены. Более того, используемый им алгоритм по современным стандартам считается «слабым». (Версия
rand
GLIBC не имеет этих проблем, но переносимый код должен быть написан со знанием того, что
rand
не является лучшим API для использования.)

ch12-rand.c
использует для получения значения в определенном интервале простую методику: оператор
%
. Эта методика использует младшие биты возвращенного значения (как при десятичном делении, когда остаток отделения на 10 или 100 использует одну или две младшие десятичные цифры). Оказывается, исторический генератор
rand
производил лучшие случайные значения в средних и старших битах по сравнению с младшими битами. Поэтому, если вы должны использовать
rand
, постарайтесь избежать младших битов. Справочная страница GNU/Linux rand(3) цитирует «Числовые рецепты на С» [129] , которая рекомендует эту методику:

129

Numerical Recipes in С. The Art of Scientific Computing,, 2nd edition, by William H. Press, Brian P. Plannery, Saul A. Teukolsky, and William T. Vetterling. Cambridge University Press, USA, 1993, ISBN 0-521-43108-5 — Примеч. автора.

j = 1+ (int)(10.0*rand/(RAND_MAX+1.0)); /* для числа от 1 до 10 */

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.

Поделиться:
Популярные книги

Я не князь. Книга XIII

Дрейк Сириус
13. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я не князь. Книга XIII

"Фантастика 2025-103". Компиляция. Книги 1-17

Поселягин Владимир Геннадьевич
Фантастика 2025. Компиляция
Фантастика:
боевая фантастика
попаданцы
альтернативная история
фэнтези
5.00
рейтинг книги
Фантастика 2025-103. Компиляция. Книги 1-17

Океан сказаний (сборник)

Сомадева
Библиотека всемирной литературы
Старинная литература:
древневосточная литература
6.25
рейтинг книги
Океан сказаний (сборник)

Последний Паладин. Том 12

Саваровский Роман
12. Путь Паладина
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Последний Паладин. Том 12

Дважды одаренный. Том III

Тарс Элиан
3. Дважды одаренный
Фантастика:
альтернативная история
аниме
фэнтези
фантастика: прочее
юмористическое фэнтези
5.40
рейтинг книги
Дважды одаренный. Том III

"Фантастика 2025-31". Компиляция. Книги 1-27

Трофимов Ерофей
Фантастика 2025. Компиляция
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
фэнтези
5.00
рейтинг книги
Фантастика 2025-31. Компиляция. Книги 1-27

Цикл романов "Целитель". Компиляция. Книги 1-17

Большаков Валерий Петрович
Целитель
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Цикл романов Целитель. Компиляция. Книги 1-17

Война Хонор

Вебер Дэвид Марк
10. Хонор Харрингтон
Фантастика:
космическая фантастика
8.67
рейтинг книги
Война Хонор

Ранчо

Стил Даниэла
Любовные романы:
современные любовные романы
7.71
рейтинг книги
Ранчо

Собрание сочинений в 15 томах. Том 7

Уэллс Герберт Джордж
Фантастика:
научная фантастика
5.00
рейтинг книги
Собрание сочинений в 15 томах. Том 7

Симеон Гордый

Балашов Дмитрий Михайлович
4. Государи московские
Научно-образовательная:
история
7.89
рейтинг книги
Симеон Гордый

Лондонские поля

Эмис Мартин
Интеллектуальный бестселлер. Читает весь мир.
Проза:
современная проза
7.11
рейтинг книги
Лондонские поля

Дневники св. Николая Японского. Том V

Японский Николай
Религия и эзотерика:
православие
христианство
религия
5.00
рейтинг книги
Дневники св. Николая Японского. Том V

Русские горки. Конец Российского государства

Калюжный Дмитрий Витальевич
Великие противостояния
Научно-образовательная:
история
политика
6.00
рейтинг книги
Русские горки. Конец Российского государства