C 试图找到一个完全随机数生成器
我在C语言中工作,我正在(拼命地)制作一个随机生成器,它不仅生成 我每次运行生成器时都会使用不同的数字,但每次运行程序时也会使用不同的序列。我几乎测试了所有在线发现的内容。我找到了两种制作好随机生成器的好方法。 第一种方法是每次使用不同的种子。但这意味着每次我都必须使用不同的随机种子,这是我最初没有解决的问题。以下是我现在尝试的方法,但它不是我想要的真正随机的:C 试图找到一个完全随机数生成器,c,windows,unix,random,time,C,Windows,Unix,Random,Time,我在C语言中工作,我正在(拼命地)制作一个随机生成器,它不仅生成 我每次运行生成器时都会使用不同的数字,但每次运行程序时也会使用不同的序列。我几乎测试了所有在线发现的内容。我找到了两种制作好随机生成器的好方法。 第一种方法是每次使用不同的种子。但这意味着每次我都必须使用不同的随机种子,这是我最初没有解决的问题。以下是我现在尝试的方法,但它不是我想要的真正随机的: int myrand(int random_seed){ random_seed = random_seed * 11035152
int myrand(int random_seed){
random_seed = random_seed * 1103515245 +12345;
return (unsigned int)(random_seed / 65536) % 32768;
}
每次调用该函数时,我将种子数增加1
第二种方法是使用时间。时间是变化的,这是随机的。我也尝试了许多方法来实现这一点。我最近的尝试是:
但是我不能使用gettimeofday函数,因为我在Windows中工作。在这个问题上,我也没有得到任何答案
有谁能帮我在Windows下用C语言实现一个随机生成器(可能使用时间)吗?或者我应该使用Unix吗?给你的RNG添加一个好的熵源 在unix下,使用/dev/random
在windows下,使用CryptoAPI-之类的工具,您需要的不是随机数生成器,而是如何使用C标准库中已经包含的随机数生成器 您只需在程序启动时对其进行一次种子设定:
srand(time(NULL));
就这些。它是可移植的,并且在每次运行程序时都会给您一个不同的序列,因为自上次运行程序以来至少已经过了一秒钟
以后再对其进行种子设定没有坏处,但也没有意义。C标准库的标题为time.h(如果使用C++,则为ctime)()。Windows和Unix将支持这些功能 我建议将time()或clock()作为随机数生成器的种子
另一种获得完全随机输入的方法是使用鼠标位置或其他受外界影响的东西。有许多方法可以实现prng,但不幸的是,它们都不是真正的随机数生成器。时间(NULL)是一个很好的方法,但我使用的是“blum-blum-shub”。它生成一位随机数,因为您明确要求Windows解决方案,我建议避免将
time(NULL)
或clock()
作为srand()
的种子,因为它们的粒度非常有限(ms)。相反,您可以使用性能计数器的结果:
LARGE_INTEGER PerformanceCount;
QueryPerformanceCounter(&PerformanceCount);
srand(PerformanceCount.LowPart);
可以通过调用来获得的频率增量率。这通常至少增加1 MHz,有时甚至增加到GHz范围。因此,它为种子提供了快速变化的来源
Edit:正如您所理解的,同样的gettimeofday()
实现也不会提供精细的粒度。它可能会在其参数中显示单词tv\u usec
,但在WIndows上,它不会像在Linux系统上那样提供微秒级的粒度。引用:
创建一个随机生成器,它不仅在每次运行生成器时生成不同的数字
随机变量的定义不包括该概念。相反,这个想法是,你有平等的机会选择任何数字,而不管之前选择的数字。这意味着理论上可以选择相同的数字两次
如果你发的是一副牌,那么这符合你的标准,没有重复。使用套牌交易方法意味着跟踪“已使用”的号码
您还应该知道PNRG(伪随机数生成器)是循环的(周期性的)。生成数字后,通常是一个大数字,然后重新开始,并完全重复数字的名称序列。UNIXrand()
函数生成范围为[0,{rand\u MAX}]的整数,其周期为2^32
真的考虑阅读这个短页:
请参阅:srand()是否有问题?您可以在如下时间对其进行种子设定:
srand(time(NULL))代码>我还尝试了srand(时间(空))但为了等待时间的改变,我不得不进行延迟。原因是我想一次生成大量随机数,我不想等待2分钟让程序生成它们。我也尝试使用毫秒,但没有成功。也许毫秒是答案,但我无法正确实现,同样的问题是我使用的是windows。@Dchris:在程序开始时,用时间为伪随机数生成器(PRNG)播种一次。然后,您可能必须确保每秒运行程序不超过一次(引入毫秒会有所帮助),但您不必在每次从PRNG读取数字时都等待一秒钟。@SteveJessop:我希望这能奏效!这仅适用于重要的随机性。从/dev/random中读取将耗尽系统的熵,当系统最终为空时将导致阻塞,直到系统收集到更多的熵。当然,OP没有说明他试图解决的问题是否与安全相关。我怀疑它没有。请注意,您可以通过这种方式对rng进行种子设定。在C++11上,您可以使用它,它可能会使用系统上任何真正随机数据的源。重新设定种子不应掉以轻心。根据PRNG算法的不同,重新播种可能有助于增加熵,但重新播种肯定有正确和错误的方法,以及基于不良重新播种的加密攻击。正如您所说的,对于简单的PRNG用例,重新播种通常是不必要的。例如,MT算法可以生成惊人的2^19937−1在它重复自身之前输入数字。其他的自行车在骑自行车前可以达到2^32个数字。