c ++ srand没有给出相同的随机数序列

时间:2015-02-06 21:06:09

标签: c++ srand

我有一个使用rand()和srand()的优化算法。为了能够测试行为,我将种子设置为特定的数字,以便在程序的不同运行中获得相同的随机数序列。

#define RN rand()/(RAND_MAX+1.0)
int main(int argc, char **argv)
{
    unsigned int seed=47456536;
    srand(seed);
    // a lot of stuff including RN
}

问题是,在不同的运行中,我得到不同的数字序列。这可能吗?

2 个答案:

答案 0 :(得分:8)

首先关闭:Do not use randThere are enough better alternatives

即使2011版的C标准 1 也在脚注295中说明:

  

无法保证所产生的随机序列的质量和一些实现   已知产生具有令人沮丧的非随机低阶位的序列。应用程序   特殊要求应使用已知足以满足其需求的发电机。

如果没有说服你,请让我加一些重点:

  

无保证 关于生成的随机序列的质量和一些实现   已知会产生具有 令人沮丧的非随机 低阶位的序列。应用程序 with   特殊要求应该使用已知足够的发电机[阅读:不是这一个]来满足他们的需求。

但是,如果您决定出于任何原因使用它, C99 7.20.2.2和C11 7.22.2.2都定义srand功能如下:

  

(2)srand函数使用该参数作为新随机伪随机序列的种子   后续调用rand返回的数字。如果srand随后被调用   在相同的种子值下,应重复伪随机数的序列。如果兰特是   在对srand进行任何调用之前调用,应生成相同的序列   当第一次使用种子值1调用srand时。

     

(3)[...]实现应该表现得好像没有库函数调用srand函数。

这意味着 2 您的标准库被破坏,您正在调用未定义的行为(例如写入您不应该写入的内存)或者确实具有其他一些非确定性来源。您肯定知道,最常见的非确定性来源是线程和读取输入(键盘,时间等)。请注意,从多个线程调用rand / srand本质上是不安全的 3 ,而不仅仅是执行顺序。

由于rand随机数生成工具只有一个中心状态,您还应该知道that libraries used by your code can modify it as well,因此您的问题可能隐藏在对库函数的无辜调用中(标准库除外) )。

我还要重申,rand使用的算法未指定 。因此,不同的编译器(更具体地说,不同的标准库)可以并且将产生不同的随机数。

最后,如果可能的话,让我再说一次should not use rand

如果对您现在应该做什么有任何疑问,请参阅以下完全符合标准的srandrand实施:

#define RAND_MAX 32767
static int _rand_state = 1;
void srand(unsigned int seed) { _rand_state = (int)(seed % 32768); }
int rand() { return (++_rand_state) % 32768; }

<子> 的脚注:

<子> 1.如果您使用的是linux,那么手册页rand(3)同意:&#34;在旧的rand()实现上,以及在不同系统上的当前实现,低位比随机更低的随机位订单位。当需要良好的随机性时,请勿在可移植的应用程序中使用此功能。&#34;

<子> 2.结合C99 7.20.2.1/3或C11 7.22.2.1/3,保证实现的行为就像任何标准库函数永远不会调用srandrand一样。

<子> 3. C11在使用这些函数时明确允许数据竞争(C11 7.22.2.1/3和C11 7.22.2.2/3),如果知道线程和线程安全的概念,C99也会这样做。

答案 1 :(得分:4)

不,因为随机数生成器被定义为给定固定种子的确定性。

你的&#34;很多东西,包括RN&#34;可能会根据时间重新排序事情?

编辑:&#34;重新排序&#34;:是否存在可能影响请求随机数的顺序的外部因素(时间,来自文件的数据,多个线程被安排等)?

编辑:你可以尝试使用像Boost的RNG这样的东西;我对boost::mt19937有很好的经验,而且你可以拥有发电机&#34;对象&#34;根除你使用的某个图书馆也可能通过rand得到随机数字,弄乱你的序列。