Новосибирский Государственный Университет
Опубликован: 26.08.2005 | Доступ: свободный | Студентов: 19045 / 3448 | Оценка: 4.07 / 3.55 | Длительность: 13:11:00
ISBN: 978-5-9556-0057-4
Лекция 16:

Функции в примерах

< Лекция 15 || Лекция 16: 123456
Аннотация: Функция получения случайных чисел. Поиск узлов из простых чисел. Матрица инцидентности. Структуры данных. Работа с файлами. Все операции со стеком. Примеры из графики, все преобразования трехмерного пространства.

Функция получения случайных чисел

Сейчас мы покажем генератор псевдослучайных чисел. Это означает, что фактическая последовательность чисел предсказуема, но они разбросаны довольно равномерно в пределах возможного диапазона значений.

Схема начинает с числа, называемого "зерно". Она использует его для создания нового числа, которое становится новым зерном. Затем новое зерно можно использовать для создания более нового зерна и т.д. Чтобы эта схема работала, функция случайных чисел должна помнить зерно, которое она использовала при последнем вызове. Отметим, здесь нужно использовать статическую переменную!

/* Первая версия функции 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("%d\n",rand( ));
}

Программа проработала один раз:

Введите свое значение зерна.

1
-26514
-4449
20196
-20531
3882

Используя значение 1 для переменной seed, получаем те же значения, что и прежде. Введем значение 2 и посмотрим, что получится:

2
23832
20241
-1858
-30417
-16204

Мы получили другую последовательность чисел.

< Лекция 15 || Лекция 16: 123456
Иван Руднев
Иван Руднев
Фраза "Структурная переменная описывается с помощью переменной структурного типа" на мой Взгляд является тафтология. Из нее сложно понять суть утверждения. Хотелось бы полке понятного описания.
Руслан Поддубный
Руслан Поддубный

"

printf("Добро пожаловать!\n");  - на консоль выводится непонятный набор знаков вместо русского текста.