C++ rand() 生成相同的数字 - 即使在我的主要内容中有 srand(time(NULL)) !
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3032726/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
rand() generating the same number – even with srand(time(NULL)) in my main!
提问by Nick Sweet
So, I'm trying to create a random vector (think geometry, not an expandable array), and every time I call my random vector function I get the same x value, though y and z are different.
所以,我试图创建一个随机向量(想想几何,而不是一个可扩展的数组),每次我调用我的随机向量函数时,我都会得到相同的 x 值,尽管 y 和 z 不同。
int main () {
srand ( (unsigned)time(NULL));
Vector<double> a;
a.randvec();
cout << a << endl;
return 0;
}
using the function
使用函数
//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;
}
For some reason, randx will consistently return 8, whereas the other numbers seem to be following the (pseudo) randomness perfectly. However, if I put the call to define, say, randy before randx, randy will always return 8.
出于某种原因,randx 将始终返回 8,而其他数字似乎完全遵循(伪)随机性。但是,如果我在 randx 之前调用定义,比如说,randy,randy 将始终返回 8。
Why is my first random number always 8? Am I seeding incorrectly?
为什么我的第一个随机数总是 8?我播种不正确吗?
采纳答案by Nick Sweet
The issue is that the random number generator is being seeded with a values that are very close together - each run of the program only changes the return value of time() by a small amount - maybe 1 second, maybe even none! The rather poor standard random number generator then uses these similar seed values to generate apparently identical initial random numbers. Basically, you need a better initial seed generator than time() and a better random number generator than rand().
问题是随机数生成器的种子值非常接近 - 程序的每次运行只会少量更改 time() 的返回值 - 可能是 1 秒,甚至可能没有!相当差的标准随机数生成器然后使用这些相似的种子值来生成明显相同的初始随机数。基本上,您需要一个比 time() 更好的初始种子生成器和一个比 rand() 更好的随机数生成器。
The actual looping algorithm used is I think lifted from Accelerated C++ and is intended to produce a better spread of numbers over the required range than say using the mod operator would. But it can't compensate for always being (effectively) given the same seed.
我认为实际使用的循环算法是从 Accelerated C++ 中提取的,旨在在所需范围内产生更好的数字分布,而不是使用 mod 运算符。但它无法弥补总是(有效地)给予相同的种子。
回答by Justin Ardini
I don't see any problem with your srand()
, and when I tried running extremely similar code, I did not repeatedly get the same number with the first rand()
. However, I did notice another possible issue.
我没有发现您srand()
的rand()
. 但是,我确实注意到了另一个可能的问题。
do randx = (rand()/bucket_size)+min;
while (randx <= min && randx >= max);
This line probably does not do what you intended. As long as min < max
(and it always should be), it's impossible for randx
to be both less than or equal to min
and greater than or equal to max
. Plus, you don't need to loop at all. Instead, you can get a value in between min and max using:
这条线可能不符合您的意图。只要min < max
(并且始终应该如此),就不可能randx
既小于或等于min
又大于或等于max
。另外,您根本不需要循环。相反,您可以使用以下方法获取 min 和 max 之间的值:
randx = rand() % (max - min) + min;
回答by M. Williams
Also to mention, you can even get rid of that strange bucket_size
variable and use the following method to generate numbers from a
to b
inclusively:
另外提一下,你甚至可以摆脱那个奇怪的bucket_size
变量,使用下面的方法来从生成数字a
到b
包括性:
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;
回答by fredoverflow
A simple quickfix is to call rand
a few times after seeding.
一个简单的快速修复是rand
在播种后调用几次。
int main ()
{
srand ( (unsigned)time(NULL));
rand(); rand(); rand();
Vector<double> a;
a.randvec();
cout << a << endl;
return 0;
}
Just to explain better, the first call to rand() in four sequential runs of a test program gave the following output:
为了更好地解释,在测试程序的四次连续运行中第一次调用 rand() 给出了以下输出:
27592
27595
27598
27602
Notice how similar they are? For example, if you divide rand()
by 100, you will get the same number 3 times in a row. Now take a look at the second result of rand() in four sequential runs:
注意到它们有多相似了吗?例如,如果除以rand()
100,您将连续 3 次得到相同的数字。现在看看 rand() 在四次连续运行中的第二个结果:
11520
22268
248
10997
This looks much better, doesn't it? I really don't see any reason for the downvotes.
这看起来好多了,不是吗?我真的不认为有任何理由不赞成。
回答by Waterybob
I had the same problem exactly. I fixed it by moving the srand() call so it was only called once in my program (previously I had been seeding it at the top of a function call). Don't really understand the technicalities - but it was problem solved.
我完全有同样的问题。我通过移动 srand() 调用来修复它,因此它在我的程序中只被调用一次(以前我一直在函数调用的顶部播种)。不太了解技术细节 - 但问题解决了。
回答by CaptainFox
Not directly related to the code in this question, but I had same issue with using
srand ((unsigned)time(NULL))
and still having same sequence of values being returned from following calls to rand()
.
与此问题中的代码没有直接关系,但我在使用时遇到了同样的问题,
srand ((unsigned)time(NULL))
并且仍然从对rand()
.
It turned out that srand needs to called on each thread you are using it on separately. I had a loading thread that was generating random content (that wasn't random cuz of the seed issue). I had just using srand in the main thread and not the loading thread. So added another srand ((unsigned)time(NULL))
to start of loading thread fixed this issue.
事实证明, srand 需要分别调用您正在使用它的每个线程。我有一个生成随机内容的加载线程(这不是种子问题的随机原因)。我只是在主线程中使用了 srand 而不是加载线程。所以添加了另一个srand ((unsigned)time(NULL))
开始加载线程修复了这个问题。
回答by Anonymous Coward
Your implementation, through integer division, ignores the smallest 4-5 bit of the random number. Since your RNG is seeded with the system time, the first value you get out of it will change only (on average) every 20 seconds.
您的实现,通过整数除法,忽略随机数的最小 4-5 位。由于您的 RNG 是系统时间的种子,因此您从中获得的第一个值只会(平均)每 20 秒改变一次。
This should work:
这应该有效:
randx = (min) + (int) ((max - min) * rand() / (RAND_MAX + 1.0));
where
在哪里
rand() / (RAND_MAX + 1.0)
is a random double value in [0, 1) and the rest is just shifting it around.
是 [0, 1) 中的随机双精度值,其余的只是移动它。