2011-02-08 78 views

回答

8

这是常用的解决方案:

srand (time(NULL)); 

的所有C代码的执行是确定性的,所以你必须在东西带给你每次调用srand时间是不同的。在这种情况下是时候了。

或者您可以从/dev/random(与其他文件一样打开)读取数据。

+3

如果程序在第二运行若干次,相同的随机数序列,将产生多次如,使用相同的种子! – Abhi 2011-02-08 09:22:20

11

为了生成一系列pseudorandom数字,生成器需要为seeded。种子完全决定了将要产生的数字序列。在C中,您按照您的指示种子srand。根据srand(3)手册页,没有明确的播种意味着生成器将使用1作为种子。这扩大了为什么你总是看到相同的数字(但要记住,序列本身是非常随机的,质量取决于使用的发生器,即使序列每次都是相同的)。

用户mzabsky指出,一种让人感觉随机的种子是种子随着时间的推移。另一种常见的方法(我刚才看到mzabsky也指出 - 对不起)是将发电机与系统的随机数发生器的内容一起播种,该发生器从由诸如鼠标移动,磁盘定时等事物提供的熵池中提取。不能从系统生成器中获得很多随机性,因为它无法收集到足够的熵。但是如果你只是从中得到一颗种子,你就会随机选择一个随机数字序列。这里有一个如何做,在C Linux中的示例:

unsigned int seed; 
FILE* urandom = fopen("/dev/urandom", "r"); 
fread(&seed, sizeof(int), 1, urandom); 
fclose(urandom); 
srand(seed); 

在康拉德梅耶的回答来看,我想我会更详细一点。我会将随机数的使用分为三类:

  1. 变化。如果您使用随机数字在游戏中创建看似随机或变化的行为,则无需对该主题或选择适当的种子进行非常认真的思考。随着时间的推移种子,并看看其他解决方案,如果这不够好。在这种情况下,即使相对较差的RNG也会显得很随机。
  2. 科学模拟。如果您使用随机数进行科学工作,例如蒙特卡罗计算,则需要小心选择优质发生器。你的种子应该是固定的(或用户可更改的)。你不要想变异(在上面的意义上);你需要确定性的行为,但很好的随机性。
  3. 加密。你会非常小心。这可能超出了本主题的范围。
3

小心;在linux上的rand(3)联机帮助页上指出,某些平台上的rand()实现不会在较低位上提供良好的随机性。出于这个原因,你可能想用库来获取真正的随机数。 Glib提供了有用的功能,如g_random_int_range(),这可能会更好地满足您的目的。

4

如果您使用的是OS不提供的/ dev /随机,然后使用像什么如下所示

timeval t1;
gettimeofday(&t1, NULL);
srand(t1.tv_usec * t1.tv_sec);

这段代码可以很容易地移植到其他的操作系统。

要改善种子,您可以将上面显示的时间产品(可能使用MD5或校验和算法)与主机的MAC地址进行组合。

timeval t1;
gettimeofday(&t1, NULL);
unsigned int seed = t1.tv_usec * t1.tv_sec;

unsigned char mac_addr[6];
getMAC(&mac_addr);
improveSeedWithMAC(&seed, mac_addr) ; // MD5 or checksum ...

srand(seed);