C++ std::random_shuffle 每次产生相同的结果

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14221763/
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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 18:07:49  来源:igfitidea点击:

std::random_shuffle produces same result each time

c++

提问by panthro

Possible Duplicate:
How to make sure that std::random_shuffle always produces a different result?

可能的重复:
如何确保 std::random_shuffle 总是产生不同的结果?

I have an array and I wish to shuffle it, I use:

我有一个数组,我想对其进行洗牌,我使用:

answerPositionArray[0] = 100;
answerPositionArray[1] = 400;
answerPositionArray[2] = 800;
std::random_shuffle(answerPositionArray, answerPositionArray + 2);

But every time I run my program the same shuffle comes out, 400, 800, 100. Is there a way to get the shuffle to be different every time? Eg. first time 100, 800, 400 then 800, 400, 100 etc.

但是每次我运行我的程序时,都会出现相同的 shuffle,400、800、100。有没有办法让 shuffle 每次都不同?例如。第一次是 100、800、400,然后是 800、400、100 等。

Thanks

谢谢

回答by bames53

std::random_shuffle(b,e)uses an implementation-defined source of randomness and so this cannot be portably controlled. Typically implementations use std::rand()and so using std::srand()to seed the rng often works.

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);

There is an overload of std::random_shuffle()which takes as a third parameter a random number generator. You can use this form to define the source of randomness so you can seed it.

有一个重载,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 introduces another algorithm std::shufflewhich takes a UniformRandomNumberGenerator, allowing you to use the C++11 <random>generators:

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);


Your comments indicate that the problem was that you were not shuffling the entire array, that you were only shuffling the first two elements and the last element was not being touched.

您的评论表明问题在于您没有混洗整个数组,您只是混洗了前两个元素,而没有触及最后一个元素。

This is a good demonstration of how using magic numbers, as in your code:

这是如何使用幻数的一个很好的演示,就像在您的代码中一样:

std::random_shuffle(answerPositionArray, answerPositionArray + 2);
                                                               ^
                                                               |
                                                 magic number --

can be error prone. Instead you should try to write code that works independently of such values.

可能容易出错。相反,您应该尝试编写独立于这些值工作的代码。

// 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));

Or once you can use C++11 you can use std::beginand std::endon arrays:

或者,一旦您可以使用 C++11,您就可以在数组上使用std::beginstd::end

std::random_shuffle(std::begin(answerPositionArray), std::end(answerPositionArray));

Or you can implement beginand endfunctions yourself in C++03 using the above array size trick:

或者您可以使用上述数组大小技巧在 C++03 中自己实现beginend运行:

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; }

These methods allow you to avoid having to use a magic number for the array size, and so when you write or modify code you'll be less likely to mistakenly use the wrong value.

这些方法使您可以避免对数组大小使用幻数,因此当您编写或修改代码时,您不太可能错误地使用错误的值。

回答by KCH

C++ random numbers aren't truly random - they are generated from initial value called seed. If you don't set the seed, it will always be the same, so generated sequence won't change. std::random_shuffledepends on random number generation, so it will behave this way as well.

C++ 随机数并不是真正的随机数——它们是从称为种子的初始值生成的。如果不设置种子,它将始终相同,因此生成的序列不会改变。std::random_shuffle取决于随机数生成,因此它也会以这种方式运行。

So how to set the seed? Use:

那么如何设置种子呢?用:

srand(time(0));

before any calls to functions using random numbers. It will set the seed to current time in seconds. Don't forget to add appropritate header files.

在使用随机数调用函数之前。它将以秒为单位将种子设置为当前时间。不要忘记添加适当的头文件。