可能重复:
How to make sure that std::random_shuffle always produces a different result?
我有一个数组,我希望将其改组,我使用:
answerPositionArray[0] = 100;
answerPositionArray[1] = 400;
answerPositionArray[2] = 800;
std::random_shuffle(answerPositionArray, answerPositionArray + 2);
但每次我运行我的程序时都会出现相同的洗牌,400,800,100。有没有办法让shuffle每次都不同?例如。第一次100,800,400然后800,400,100等。
由于
答案 0 :(得分:34)
std::random_shuffle(b,e)
使用实现定义的随机源,因此无法进行可移植控制。通常,实现使用std::rand()
,因此使用std::srand()
为rng播种通常有效。
// not portable, depends on implementation defined source of randomness in random_shuffle
std::srand(some_seed);
std::random_shuffle(answerPositionArray, answerPositionArray+size);
有std::random_shuffle()
的重载,它将随机数生成器作为第三个参数。您可以使用此表单来定义随机源,以便您可以播种它。
struct RNG {
int operator() (int n) {
return std::rand() / (1.0 + RAND_MAX) * n;
}
};
std::srand(seed);
std::random_shuffle(answerPositionArray, answerPositionArray+size, RNG());
C ++ 11引入了另一个算法std::shuffle
,它采用UniformRandomNumberGenerator,允许您使用C ++ 11 <random>
生成器:
std::random_device r;
std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
std::mt19937 eng(seed);
std::shuffle(std::begin(answerPositionArray), std::end(answerPositionArray), eng);
你的评论表明问题在于你没有改变整个阵列,你只是在洗牌前两个元素,而最后一个元素没有被触及。
这是一个很好的演示如何使用魔术数字,如代码中所示:
std::random_shuffle(answerPositionArray, answerPositionArray + 2);
^
|
magic number --
可能容易出错。相反,你应该尝试编写独立于这些值的代码。
// trick for getting an array size
template<typename T, int N> int array_size(T (&)[N]) { return N; }
int answerPositionArray[] = {100, 400, 800};
std::random_shuffle(answerPositionArray,
answerPositionArray + array_size(answerPositionArray));
或者一旦你可以使用C ++ 11,就可以在数组上使用std::begin
和std::end
:
std::random_shuffle(std::begin(answerPositionArray), std::end(answerPositionArray));
或者您可以使用上面的数组大小技巧在C ++ 03中自己实现begin
和end
函数:
template<typename T, int N> T *begin(T (&a)[N]) { return a; }
template<typename T, int N> T *end(T (&a)[N]) { return a + N; }
这些方法允许您避免对数组大小使用幻数,因此当您编写或修改代码时,您不太可能错误地使用错误的值。
答案 1 :(得分:21)
C ++随机数并非真正随机 - 它们是从名为seed的初始值生成的。如果不设置种子,它将始终相同,因此生成的序列不会更改。 std::random_shuffle
取决于随机数生成,因此它也会以这种方式运行。
那么如何设置种子?使用:
srand(time(0));
在使用随机数调用函数之前。它会将种子设置为当前时间(以秒为单位)。不要忘记添加appropritate头文件。