2013-01-08 50 views
10

可能重复:
How to make sure that std::random_shuffle always produces a different result?的std :: random_shuffle产生相同的结果,每次

我有一个数组,我希望洗牌它,我使用:

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

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

由于

+17

你忘了给我看,'std :: srand(std :: time(0))',从我看到的。 – Rapptz

+0

我应该在代码中放置哪一行? – panthro

+2

@ user1013512在任何呼叫任意 – lcs

回答

21

C++的随机数不是真正的随机 - 它们是从初始值称为种子生成的。如果你没有设置种子,它将永远是一样的,所以生成的序列不会改变。 std::random_shuffle取决于随机数的生成,所以它也会以这种方式表现。

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

srand(time(0)); 

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

+0

我将它添加到:answerPositionArray [0] = 100; \t answerPositionArray [1] = 400; \t answerPositionArray [2] = 800; \t std :: srand(std :: time(0)); \t std :: random_shuffle(answerPositionArray,answerPositionArray + 2); – panthro

+2

它不起作用。 – panthro

+0

您是否在测试之间至少等待一秒钟? – KCH

26

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::beginstd::end

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

或者你可以在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; } 

这些方法允许您避免使用数组大小​​的幻数,所以whe当你编写或修改代码时,你不太可能错误地使用错误的值。

+0

不使用C++ 11 – panthro

+4

@ user1013512:阅读整篇文章。他包含C++ 98/03和C++ 11的解决方案。 –

+0

@ user1013512然后你想要我提到的'std :: random_shuffle'的第二重载。或者,如果您可以验证您所关心的所有实现都使用'std :: rand',那么您可以依赖该实现细节并使用'std :: srand()'。 – bames53

相关问题