Инициализация генератора псевдослучайных чисел

Материал из MediaWiki
Версия от 14:23, 4 мая 2018; lor>Cetjs2 (Откат правок Abc123456 (обсуждение) к версии Mandala)
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)
Перейти к навигации Перейти к поиску

Инициализация генератора псевдослучайных чисел зачастую является наболевшим вопросом. Приведу код, который содержит в себе два способа инициализации.

#include <stdio.h>		// printf
#include <stdlib.h>		// random number functions
#include <sys/time.h>		// gettimeofday
#include <limits.h>		// LONG_MAX
#include <math.h>		// floor
#include <unistd.h>		// read
#include <sys/types.h>		// open
#include <sys/stat.h>		// open
#include <fcntl.h>		// open

double dtime(){
	double t;
	struct timeval tv;
	gettimeofday(&tv, NULL);
	t = tv.tv_sec + ((double)tv.tv_usec)/1e6;
	return t;
}

void urandom_ini(){
	double tt = dtime() * 1e6;
	double mx = (double)LONG_MAX;
	srand48((long)(tt - mx * floor(tt/mx)));
}

void dev_random_ini(){
	long r_ini;
	int fd = open("/dev/random", O_RDONLY);
	if(-1 == fd){fprintf(stderr,"Error open /dev/random!\n"); urandom_ini(); return;}
	if(sizeof(long) != read(fd, &r_ini, sizeof(long))){
		fprintf(stderr,"Error read /dev/random!\n"); urandom_ini();
		close(fd); return;
	}
	close(fd);
	srand48(r_ini);
}

int main(int argc, char **argv){
	int i;
	printf("\trandom\t\tdrand48\n");
	dev_random_ini();
	for(i = 0; i < 10; i++){
		printf("\t%ld\t%g\n", random(), drand48());
	}
	printf("\n");
	return 0;
}

Функция dev_random_ini() пытается инициализировать генератор псевдослучайных чисел при помощи сложного генератора ядра, работающего на основе "энтропии" - совокупности большого количества разных псевдослучайных величин (например, движения мышью, нажатия клавиш клавиатуры и т.п.).

Если этот инициализатор не срабатывает, запускается менее надежный инициализатор на основе значения текущего времени.