我有一个使用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
}
问题是,在不同的运行中,我得到不同的数字序列。这可能吗?
答案 0 :(得分:8)
首先关闭:Do not use rand
。 There 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
。
如果对您现在应该做什么有任何疑问,请参阅以下完全符合标准的srand
和rand
实施:
#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,保证实现的行为就像任何标准库函数永远不会调用srand
和rand
一样。
子>
<子> 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
得到随机数字,弄乱你的序列。