我有一个包含两个随机源的类.
std::random_device rd;
std::mt19937 random_engine;
Run Code Online (Sandbox Code Playgroud)
我std::mt19937打电话来播种std::random_device.如果我想生成一个数字并且我不关心重复性,我应该打电话rd()还是random_engine()?
在我的特定情况下,我确信两者都可以正常工作,因为这将在某些网络代码中调用,其中性能不是很高,结果不是特别敏感.但是,我对何时使用硬件熵以及何时使用伪随机数的一些"经验法则"感兴趣.
目前,我只使用std::random_device我的std::mt19937引擎播种,以及我的程序需要的任何随机数代,我使用std::mt19937引擎.
编辑:以下是我正在使用此特定示例的解释:
这是一个游戏程序.该特定游戏允许用户在开始对抗对手之前定制他们的"团队".设置战斗的一部分涉及将团队发送到服务器.我的程序有几个团队,并使用随机数来确定要加载的团队.每次新的战斗都会调用std::random_device种子伪随机数生成器.我记录了战斗的初始状态,其中包括我随机选择的这个团队和初始种子.
我在这个问题中询问的特定随机数是随机团队选择(在没有让对手提前知道我正在使用哪个团队,但不是任务关键的情况下,这是有益的),但我是什么我真的在寻找是一个经验法则.它是精细始终使用std::random_device,如果我不需要我的号码的重复,或者是有使用起来比熵可以更快地采集的真正危险?
Joh*_*lay 10
据我所知,标准做法是为随机数生成器播种一个不是由计算机计算的数字(但来自一些外部的,不可预测的来源).这应该是你的rd()函数的情况.从那时起,您可以为所需的每个伪随机数调用伪随机数生成器(PRNG).
如果您担心数字不够随机,那么您应该选择不同的PRNG.熵是稀缺和宝贵的资源,应该这样对待.虽然,你现在可能不需要那么多随机数,但是你可能在将来; 或其他应用程序可能需要它们.您希望每当应用程序请求时,该熵都可用.
听起来,对于您的应用,mersenne twister可以很好地满足您的需求.玩游戏的人不会觉得加载的团队不是随机的.
如果您不使用它进行加密,那么很好地重复使用播种的mt19937 random_engine.
对于本答案的其余部分,我假设您在网络代码中使用随机数进行加密.简而言之,mt19937不适合这种用途.
http://en.wikipedia.org/wiki/Mersenne_twister#Disadvantages
随着时间的推移,您可能会泄漏信息(可能是间接的),以便攻击者可以开始预测随机数.至少在理论上,但这就是它的意义所在.来自维基百科
...因为这个数字是
生成未来迭代的状态向量的大小,所以允许人们预测所有未来的迭代.
防止随机数生成信息泄露给用户的简单方法是使用单向散列函数,但还有更多功能.您应该使用为此目的设计的随机数生成器:
http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator
各种示例(带代码)可在此处找到http://xlinux.nist.gov/dads/HTML/pseudorandomNumberGen.html
如果您需要模拟或游戏的随机性,那么您正在做的很好.只需调用随机设备一次,然后使用随机播种的伪RNG完成其他所有操作.作为奖励,您应该将种子值存储在日志文件中,以便以后可以重放伪随机序列:
auto const seed = std::random_device()();
// save "seed" to log file
std::mt19937 random_engine(seed);
Run Code Online (Sandbox Code Playgroud)
(对于多个线程,使用主线程中的PRNG为生成的线程中的其他PRNG生成种子.)
如果你需要很多真正的随机性用于加密目的,那么PRNG永远不是一个好主意,因为长序列的输出包含的随机性比真正的随机性少得多,即你可以从一个小的子集中预测所有的随机性.如果您需要真正的随机性,您应该从一些不可预测的来源(例如热传感器,用户键盘/鼠标活动等)收集它.Unix /dev/random可能是一个"真正的随机性"源,但它可能不会很快填满.
| 归档时间: |
|
| 查看次数: |
15692 次 |
| 最近记录: |