15

所以,我正在尝试创建一个随机向量(想想几何,而不是可扩展数组),每次我调用我的随机向量函数时,我都会得到相同的 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?我播种不正确吗?

4

7 回答 7

9

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

我认为使用的实际循环算法是从 Accelerated C++ 提升而来的,旨在在所需范围内产生比使用 ​​mod 运算符更好的数字分布。但它不能补偿总是(有效地)给予相同的种子。

于 2010-06-13T16:00:58.640 回答
5

我看不出你的 有任何问题srand(),当我尝试运行极其相似的代码时,我并没有反复得到与第一个相同的数字rand()。但是,我确实注意到了另一个可能的问题。

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

这条线可能不符合您的预期。只要min < max(并且总是应该如此),就不可能randx既小于等于min又大于等于max。另外,您根本不需要循环。相反,您可以使用以下方法获得介于 min 和 max 之间的值:

randx = rand() % (max - min) + min;
于 2010-06-13T15:34:08.977 回答
4

我有同样的问题。我通过移动 srand() 调用来修复它,因此它只在我的程序中被调用一次(以前我一直在函数调用的顶部播种它)。不太了解技术细节-但问题已解决。

于 2012-02-22T14:32:57.570 回答
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;
于 2010-06-13T15:33:25.307 回答
2

一个简单的快速修复是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

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

于 2010-06-13T15:26:14.107 回答
1

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

这应该有效:

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

在哪里

rand() / (RAND_MAX + 1.0)

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

于 2010-06-13T16:17:49.007 回答
0

与此问题中的代码没有直接关系,但我在使用时遇到了同样的问题, srand ((unsigned)time(NULL))并且仍然从以下调用返回相同的值序列rand()

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

于 2018-12-05T12:14:54.677 回答