当前位置:  开发笔记 > 编程语言 > 正文

建议初始化srand的方法?

如何解决《建议初始化srand的方法?》经验,为你挑选了8个好方法。

我需要一种'好'的方法来初始化C++中的伪随机数生成器.我发现一篇文章指出:

为了生成类似随机数的数字,srand通常被初始化为一些独特的值,就像那些与执行时间相关的值.例如,函数时间返回的值(在标题ctime中声明)每秒都不同,这对于大多数随机需求来说足够独特.

Unixtime对我的应用来说并不是很有特色.有什么更好的方法来初始化它?奖励点是否可移植,但代码主要在Linux主机上运行.

我正在考虑做一些pid/unixtime数学来得到一个int,或者可能从中读取数据/dev/urandom.

谢谢!

编辑

是的,我实际上是每秒多次启动我的应用程序而且我遇到了碰撞.



1> Jonathan Wri..:

这就是我用于可以频繁运行的小命令行程序(每秒多次):

unsigned long seed = mix(clock(), time(NULL), getpid());

混合的地方是:

// http://www.concentric.net/~Ttwang/tech/inthash.htm
unsigned long mix(unsigned long a, unsigned long b, unsigned long c)
{
    a=a-b;  a=a-c;  a=a^(c >> 13);
    b=b-c;  b=b-a;  b=b^(a << 8);
    c=c-a;  c=c-b;  c=c^(b >> 13);
    a=a-b;  a=a-c;  a=a^(c >> 12);
    b=b-c;  b=b-a;  b=b^(a << 16);
    c=c-a;  c=c-b;  c=c^(b >> 5);
    a=a-b;  a=a-c;  a=a^(c >> 3);
    b=b-c;  b=b-a;  b=b^(a << 10);
    c=c-a;  c=c-b;  c=c^(b >> 15);
    return c;
}


涉及pid的好主意.代码源链接已经过时,它仍然[存档](http://web.archive.org/web/20070111091013/http://www.concentric.net/~Ttwang/tech/inthash.htm) - 该文本中名为"Robert Jenkins'96 bit Mix Function"的特定代码的来源实际上也是链接的:http://burtleburtle.net/bob/hash/doobs.html

2> Martin York..:

最好的答案是使用Boost随机数的东西.或者,如果您有权访问C++ 11,请使用标头.

但是如果我们谈论的话rand(),srand()
最好的方法就是使用time():

int main()
{
    srand(time(NULL));

    ...
}

一定要在程序开始时这样做,而不是每次打电话都这样做rand()!

每次启动时,time()都将返回一个唯一值(除非您每秒多次启动应用程序).在32位系统中,它只会每60年重复一次.

我知道你不认为时间足够独特但我觉得很难相信.但我知道这是错的.

如果您同时启动大量应用程序副本,则可以使用具有更高分辨率的计时器.但是在价值重复之前,你会冒更短时间的风险.

好的,所以如果你真的认为你一秒钟就开始了多个应用程序.
然后在计时器上使用更精细的颗粒.

 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.
 }


实际上,我正在启动我的应用程序的多个实例一秒钟:)
我看到某个解决方案适用于timeval/gettimeofday ....啊,是的,我自己!! 你批评它非常糟糕,虽然机会是1/1000000它会重复(你做的假设相同).而你的是1/60000.所以,这是我的解决方案,更糟糕的是,它呈现为你的.
1)不要假设时钟分辨率是1/1000000.2)我的概率是1/2147483648(注意tv_sec).3)种子重复间隔24天(应用程序之间的交互也很重要).
“重复的种子相隔24天”您每秒有1000次碰撞。
将“ tv_usec”除以1000会丢弃所有熵。毫秒很容易预测,实际上,在不到一毫秒的时间内运行一次程序很容易...

3> Evan Teran..:

如果你需要一个更好的随机数生成器,不要使用libc rand.而只是使用类似/dev/random/dev/urandom直接的东西(int直接从它或类似的东西读取).

libc rand唯一真正的好处是给定一个种子,它是可预测的,有助于调试.


您不应该从`/ dev/urandom`重复读取随机数,只是为了种子.它慢得多,耗尽了系统熵池.

4> shoosh..:

在Windows上:

srand(GetTickCount());

提供比time()自毫秒以来更好的种子.


@floele绕零表示它每49.7天从零开始计数,而不是在49.7天的正常运行时间后无法使用.

5> bames53..:

C++ 11 random_device

如果你需要合理的质量,那么你不应该首先使用rand(); 你应该使用图书馆.它提供了许多强大的功能,例如各种引擎,用于不同的质量/尺寸/性能权衡,重新进入和预定义的分发,因此您不会最终弄错它们.它甚至可以提供对非确定性随机数据的轻松访问(例如,/ dev/random),具体取决于您的实现.

#include 
#include 

int main() {
    std::random_device r;
    std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
    std::mt19937 eng(seed);

    std::uniform_int_distribution<> dist{1,100};

    for (int i=0; i<50; ++i)
        std::cout << dist(eng) << '\n';
}

eng是随机性的来源,这里是mersenne twister的内置实现.我们使用random_device对其进行播种,在任何体面的实现中,random_device都是非威慑性的RNG,而seed_seq用于组合超过32位的随机数据.例如,在libc ++中,random_device默认访问/ dev/urandom(尽管你可以给它另一个文件来访问).

接下来,我们创建一个分布,这样,给定一个随机源,重复调用分布将产生从1到100的整数均匀分布.然后我们重复使用分布并打印结果.



6> user39307..:

最好的方法是使用另一个伪随机数生成器.Mersenne twister(和Wichmann-Hill)是我的推荐.

http://en.wikipedia.org/wiki/Mersenne_twister


这根本没有解决问题,你如何为MT PRNG播种?
如果您可以使用更好的RNG,为什么要用它来播种标准RNG呢?只需使用更好的一个!

7> FL4SOF..:

我建议你在mozilla代码中看到unix_random.c文件.(猜它是mozilla/security/freebl/...)它应该在freebl库中.

它使用系统调用信息(如pwd,netstat ....)来为随机数生成噪声;它被编写为支持大多数平台(可以获得奖励积分:D).



8> Edouard A...:

您必须问自己的真正问题是您需要的随机性质量.

libc random是一个LCG

无论您提供什么样的输入,随机性的质量都会很低.

如果您只需要确保不同的实例具有不同的初始化,则可以混合进程ID(getpid),线程ID和计时器.将结果与xor混合.对于大多数应用来说,熵应该足够了.

示例:

struct timeb tp;
ftime(&tp);   
srand(static_cast(getpid()) ^ 
static_cast(pthread_self()) ^ 
static_cast(tp.millitm));

为了获得更好的随机质量,请使用/ dev/urandom.您可以使用boost :: thread和boost :: date_time使上述代码可移植.

推荐阅读
手机用户2502852037
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有