Функция получения случайных чисел
Сейчас мы покажем генератор псевдослучайных чисел. Это означает, что фактическая последовательность чисел предсказуема, но они разбросаны довольно равномерно в пределах возможного диапазона значений.
Схема начинает с числа, называемого "зерно". Она использует его для создания нового числа, которое становится новым зерном. Затем новое зерно можно использовать для создания более нового зерна и т.д. Чтобы эта схема работала, функция случайных чисел должна помнить зерно, которое она использовала при последнем вызове. Отметим, здесь нужно использовать статическую переменную!
/* Первая версия функции rand( )*/ rand( ) { static int randx = 1; randx = (randx * 25173 + 13849)%65536; /* магическая формула */ return(randx); }
Статическая переменная randx начинает со значения 1 и изменяется при помощи магической формулы каждый раз при вызове функции. Результатом в нашей системе является число, находящееся в диапазоне -32768 до 32767. Системы с разной длиной переменной типа int будут давать различные результаты.
Проверим работу функции при помощи этого простого драйвера:
/*драйвер 1 функции rand( ) */ main( ) { int count; for(count = 1; count <= 5; count++) printf(" %d\n",rand( )); }
Получим результат:
-26514 -4449 20196 -20531 3882
Эта последовательность чисел выглядит довольно случайной. Запустим драйвер еще раз. Теперь имеем
-26514 -4449 20196 -20531 3882
Получилось абсолютно то же самое. Это и есть псевдоэффект. Каждый раз, когда работает основная программа, мы начинаем с одного и того же значения зерна, равного 1. Можно обойти эту проблему, введя вторую функцию srand( ), которая позволяет вновь устанавливать зерно в начальное значение. Хитрость заключается в том, чтобы сделать randx внешней статической переменной, известной только функциям rand( ) и srand( ). Эти две функции нужно хранить в своем собственном файле и компилировать этот файл отдельно. Вот модификатор программы:
/* Файл для rand( ) и srand( ) */ static int randx = 1; rand( ) { randx = (randx * 25173 + 13849) % 65536; return(randx); } srand(x) unsigned x; { randx = x; }
Используем другой драйвер:
/* драйвер 2 функции rand( ) */ main( ) { int count; int seed; printf(" Введите свое значение зерна.\n"); scanf("%d", & seed); srand(seed); /* установите зерно в начальное значение */ for(count = 1; count <= 5; count++) printf("%\n",rand( )); }
Программа проработала один раз:
Введите свое значение зерна.
1 -26514 -4449 20196 -20531 3882
Используя значение 1 для переменной seed, получаем те же значения, что и прежде. Введем значение 2 и посмотрим, что получится:
2 23832 20241 -1858 -30417 -16204
Мы получили другую последовательность чисел.