rand()生成相同的数字 - 即使我的主要是srand(time(NULL))!

时间:2010-06-13 15:18:36

标签: c++ random srand

所以,我正在尝试创建一个随机向量(想想几何,而不是一个可扩展的数组),每次调用我的随机向量函数时,我得到相同的x值,尽管y和z是不同的。

int main () {
    srand ( (unsigned)time(NULL));
    Vector<double> a;
    a.randvec();
    cout << a << endl;
    return 0;
}

使用函数

//random Vector
template <class T>
void Vector<T>::randvec()
{
    const int min=-10, max=10;
    int randx, randy, randz;

    const int bucket_size = RAND_MAX/(max-min);

    do randx = (rand()/bucket_size)+min;
    while (randx <= min && randx >= max);
    x = randx;

    do randy = (rand()/bucket_size)+min;
    while (randy <= min && randy >= max);
    y = randy;

    do randz = (rand()/bucket_size)+min;
    while (randz <= min && randz >= max);
    z = randz;
}

出于某种原因,randx将始终返回8,而其他数字似乎完全遵循(伪)随机性。但是,如果我在randx之前将调用定义为randy,那么randy将始终返回8.

为什么我的第一个随机数总是8?我播种不正确吗?

7 个答案:

答案 0 :(得分:8)

问题在于随机数生成器的种子值非常接近 - 程序的每次运行只会将time()的返回值改变一小部分 - 可能是1秒,甚至可能没有!然后,相当差的标准随机数发生器使用这些相似的种子值来生成明显相同的初始随机数。基本上,你需要一个比time()更好的初始种子生成器和一个比rand()更好的随机数生成器。

我认为使用的实际循环算法是从Accelerated C ++中提取出来的,旨在在所需的范围内产生比使用mod运算符更好的数字扩展。但它无法弥补总是(有效地)给予相同的种子。

答案 1 :(得分:5)

我发现srand()没有任何问题,当我尝试运行非常相似的代码时,我没有重复使用第一个rand()获得相同的数字。但是,我确实注意到了另一个可能的问题。

do randx = (rand()/bucket_size)+min;
while (randx <= min && randx >= max);

这一行可能不符合您的意图。只要min < max(并且它应该始终如此),randx就不可能小于或等于min且大于或等于max。另外,您根本不需要循环。相反,您可以使用以下方法获取最小值和最大值之间的值:

randx = rand() % (max - min) + min;

答案 2 :(得分:3)

另外,你甚至可以摆脱那个奇怪的bucket_size变量并使用以下方法ab生成数字:

srand ((unsigned)time(NULL));

const int a = -1;
const int b = 1;

int x = rand() % ((b - a) + 1) + a;
int y = rand() % ((b - a) + 1) + a;
int z = rand() % ((b - a) + 1) + a;

答案 3 :(得分:2)

一个简单的quickfix就是在播种后调用rand几次。

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

    Vector<double> a;
    a.randvec();
    cout << a << endl;
    return 0;
}

为了更好地解释,在测试程序的四个连续运行中第一次调用rand()给出了以下输出:

27592
27595
27598
27602

注意它们有多相似?例如,如果将rand()除以100,则连续3次获得相同的数字。现在看一下rand()在四个连续运行中的第二个结果:

11520
22268
248
10997

这看起来好多了,不是吗?我真的没有看到任何理由进行投票。

答案 4 :(得分:1)

我确实遇到了同样的问题。我通过移动srand()调用来修复它,所以它只在我的程序中被调用一次(之前我曾在函数调用的顶部播种它)。 不太了解技术性 - 但问题已经解决了。

答案 5 :(得分:0)

通过整数除法,您的实现会忽略随机数的最小4-5位。由于您的RNG以系统时间播种,因此您获得的第一个值将每20秒仅更改一次(平均值)。

这应该有效:

randx = (min) + (int) ((max - min) * rand() / (RAND_MAX + 1.0));

其中

rand() / (RAND_MAX + 1.0)

是[0,1]中的随机双精度值,其余的只是将其移动。

答案 6 :(得分:0)

与该问题中的代码没有直接关系,但是我在使用时遇到了同样的问题 srand ((unsigned)time(NULL)),并且在随后对rand()的调用中仍返回相同的值序列。

事实证明,srand需要分别调用您正在使用的每个线程。我有一个正在生成随机内容的加载线程(这不是种子问题的随机原因)。我只是在主线程而不是加载线程中使用了srand。因此添加了另一个srand ((unsigned)time(NULL))开始加载线程,从而解决了该问题。