初始化 srand 的推荐方法?
我需要一种好的"方法来初始化 C++ 中的伪随机数生成器.我发现 一篇文章 指出:
I need a 'good' way to initialize the pseudo-random number generator in C++. I've found an article that states:
为了生成随机类数字,srand 通常被初始化到一些独特的价值,比如那些与执行时间有关.为了例如,返回的值功能时间(在标题中声明ctime) 每秒都不同,这对大多数人来说足够独特随机需求.
In order to generate random-like numbers, srand is usually initialized to some distinctive value, like those related with the execution time. For example, the value returned by the function time (declared in header ctime) is different each second, which is distinctive enough for most randoming needs.
Unixtime 对我的应用程序来说不够独特.初始化它的更好方法是什么?如果它是可移植的,则加分,但代码将主要在 Linux 主机上运行.
Unixtime isn't distinctive enough for my application. What's a better way to initialize this? Bonus points if it's portable, but the code will primarily be running on Linux hosts.
我正在考虑做一些 pid/unixtime 数学来获得一个 int,或者可能从 /dev/urandom
读取数据.
I was thinking of doing some pid/unixtime math to get an int, or possibly reading data from /dev/urandom
.
谢谢!
编辑
是的,我实际上是在每秒多次启动我的应用程序并且遇到了冲突.
Yes, I am actually starting my application multiple times a second and I've run into collisions.
推荐答案
最好的答案是 <随机>
.如果您使用的是 C++11 之前的版本,您也可以查看 Boost random number stuff.
The best answer is to <random>
. If you are using a pre C++11 version you can alternatively look at Boost random number stuff.
但如果我们谈论的是 rand()
和 srand()
best 最简单的方法就是使用 time()
:
But if we are talking about rand()
and srand()
The best simplist way is just to use time()
:
int main()
{
srand(time(nullptr));
...
}
确保在程序开始时执行此操作,而不是每次调用 rand()
!
Be sure to do this at the beginning of your program, and not every time you call rand()
!
旁注:
注意:下面的评论中讨论了这是不安全的(这是真的,但最终不相关(继续阅读)).因此,另一种方法是从随机设备 /dev/random
(或其他一些安全的实数(er)随机数生成器)中播种.但是:不要让这让你陷入虚假的安全感.这是我们正在使用的 rand()
.即使您使用出色生成的种子对其进行播种,它仍然是可预测的(如果您有任何值,您可以预测下一个值的完整序列).这仅对生成 伪"
随机值有用.
NOTE: There is a discussion in the comments below about this being insecure (which is true, but ultimately not relevant (read on)). So an alternative is to seed from the random device /dev/random
(or some other secure real(er) random number generator). BUT: Don't let this lull you into a false sense of security. This is rand()
we are using. Even if you seed it with a brilliantly generated seed it is still predictable (if you have any value you can predict the full sequence of next values). This is only useful for generating "pseudo"
random values.
如果你想要安全"您可能应该使用 <random>
(尽管我会在安全通知网站上做更多阅读).请参阅以下答案作为起点:https://stackoverflow.com/a/29190957/14065 以获得更好的答案.
If you want "secure" you should probably be using <random>
(Though I would do some more reading on a security informed site). See the answer below as a starting point: https://stackoverflow.com/a/29190957/14065 for a better answer.
附注:使用随机设备实际上比我下面的原始建议更好地解决了每秒启动多个副本的问题(只是不是安全问题).
Secondary note: Using random device actually solves the issues with starting multiple copies per second better than my original suggestion below (just not the security issue).
回到原来的故事:
每次启动时,time() 都会返回一个唯一值(除非您每秒启动应用程序多次).在 32 位系统中,它只会每 60 年左右重复一次.
Every time you start up, time() will return a unique value (unless you start the application multiple times a second). In 32 bit systems, it will only repeat every 60 years or so.
我知道你认为时间不够独特,但我觉得这很难相信.但大家都知道我错了.
I know you don't think time is unique enough but I find that hard to believe. But I have been known to be wrong.
如果您同时启动大量应用程序副本,您可以使用分辨率更高的计时器.但是,在值重复之前,您会冒更短时间段的风险.
If you are starting a lot of copies of your application simultaneously you could use a timer with a finer resolution. But then you run the risk of a shorter time period before the value repeats.
好的,如果您真的认为自己会在一秒钟内启动多个应用程序.
然后在计时器上使用更细的颗粒.
OK, so if you really think you are starting multiple applications a second.
Then use a finer grain on the timer.
int main()
{
struct timeval time;
gettimeofday(&time,NULL);
// microsecond has 1 000 000
// Assuming you did not need quite that accuracy
// Also do not assume the system clock has that accuracy.
srand((time.tv_sec * 1000) + (time.tv_usec / 1000));
// The trouble here is that the seed will repeat every
// 24 days or so.
// If you use 100 (rather than 1000) the seed repeats every 248 days.
// Do not make the MISTAKE of using just the tv_usec
// This will mean your seed repeats every second.
}
相关文章