今天,我的朋友有一个想法,设置使用产生“使事情变得更加随机”的伪随机数的伪随机数生成器多次的种子。
在C#的示例:
// Initiate one with a time-based seed
Random rand = new Random(milliseconds_since_unix_epoch());
// Then loop for a_number_of_times...
for (int i = 0; i < a_number_of_times; i++)
{
// ... to initiate with the next random number generated
rand = new Random(rand.Next());
}
// So is `rand` now really random?
assert(rand.Next() is really_random);
但我想,这大概可以增加获得正在使用的伪随机数生成器的重复种子的机会。
请问这个
- 让事情变得更随机,
- 进行循环,通过一定数目的种子使用,或者
- 什么都不做随机性(即,既不增加也不减少)?
可在伪随机数生成任何专家给出一些详细的解释,这样我可以说服我的朋友? 我会很高兴地看到,在回答一些伪随机数生成算法解释进一步的细节。
有使用的伪随机数三个基本层次。 每个级别涵括它下面的一个。
- 意外的数字,没有特别的相关性担保。 在这个级别的发电机通常遇到的问题可能关系到你一些隐藏的相关性,也可能不会。
- 统计学无关的数与已知的非相关关系。 这些通常需要数值模拟。
- 加密的安全数字无法猜到。 当安全问题,这总是需要。
每一种是确定性的。 随机数发生器是具有一些内部状态的算法。 应用所述算法一次产生一个新的内部状态和输出数量。 播种发生器装置设置内部状态; 它并不总是种子接口允许建立每一个可能的内部状态的情况。 作为一个好的经验法则,总是假设默认库随机()函数仅在最低水平,1级运行。
为了回答您的具体问题,在问题的算法(1)可以在不增加随机性和(2)可能会降低它。 随机性的预期,因此,比年初一次播种它严格地低。 究其原因来自于短迭代周期可能存在的。 为函数的迭代循环F
是一对整数n
和k
其中F^(n) (k) = k
,其中指数是次数F
被应用。 例如, F^(3) (x) = F(F(F(x)))
如果有一个短的迭代周期,随机数将更多的往往比他们原本重复。 在提供的代码中,迭代函数是种子发电机和然后在第一个输出。
要回答一个问题,你没有听问,但它是有关获得这方面的一个理解,用毫秒计数器播种,使您的发电机故障3级,unguessability的考验。 这是因为可能的毫秒数为加密小 ,这是已知受穷举搜索的数字。 在撰写本文时,2 ^ 50应考虑加密小。 (对于任何一年加密大才算数,请找一个有信誉的专家。)现在,在一个世纪的毫秒数大约为2 ^(41.5),所以不要依赖这种形式播种出于安全目的对。
因为在没有增加你的榜样,不会增加随机性的熵 。 这仅仅是从程序的执行时间的。
除了使用基于当前时间的东西,电脑维护熵池,并与统计学随机的(或至少,不可猜测)是数据建立起来。 例如,网络数据包,或关键笔划,或硬盘驱动器之间的定时延迟读取时间。
如果你想好随机数应该打入熵池。 这些被称为密码安全伪随机数生成器 。
在C#中,看到Cryptography.RandomNumberGenerator类为正确的方式来获得一个安全的随机数。
这不会使事情变得更加“随机”。
我们的种子确定rand.next号()给我们的随机寻找,但完全确定顺序。
相反,使事情更随机的,你的代码定义一个映射,从您最初的种子到一些最后的种子,并给予相同的初始种子,你将永远结束了相同的最终的种子。
尝试使用此代码玩,你会明白我的意思(也, 这里是你可以在浏览器中运行一个版本的链接 ):
int my_seed = 100; // change my seed to whatever you want
Random rand = new Random(my_seed);
for (int i = 0; i < a_number_of_times; i++)
{
rand = new Random(rand.Next());
}
// does this print the same number every run if we don't change the starting seed?
Console.WriteLine(rand.Next()); // yes, it does
这个最后的种子随机对象,就像任何其他的随机对象。 它只是把你更多的时间则需要创建它。