random_shuffle并不是真正的随机

Chi*_*hin 9 c++ random srand

我正在使用random_shuffle像这样的矢量:

#include <algorithm>
vector <Card> deck;
//some code to add cards to the deck here
random_shuffle ( deck.begin(), deck.end() );
Run Code Online (Sandbox Code Playgroud)

运行时,卡组的内容会混淆,但重新启动程序时会保留此混合顺序.

我错过了什么?我怎样才能让它真正随意?

Joe*_*Joe 14

您需要首先使用srand为伪随机数生成器播种.

#include <algorithm>
#include <cstdlib>

...

std::srand(std::time(0));

vector <Card> deck;
//some code to add cards to the deck here
random_shuffle ( deck.begin(), deck.end() );
Run Code Online (Sandbox Code Playgroud)

请注意以上链接:

一般来说,伪随机数生成器只应在对rand()的任何调用和程序的开始之前播种一次.每次您希望生成一批新的伪随机数时,不应重复播种或重新播种.

  • `random_shuffle()`实际上没有指定使用`rand()`因此`srand()`可能没有任何影响.如果你想确定,你应该使用C++ 11表单之一,`random_shuffle(b,e,RNG)`或`shuffle(b,e,uRNG)` (8认同)

max*_*zig 8

使用当前的C++(即C++ 11),您可以使用shuffle可以将伪随机数生成器(PRNG)对象(可以播种)作为第三个参数的算法:

#include <iostream>
#include <random>
#include <algorithm>
#include <vector>
#include <string>
#include <ctime>
using namespace std;

int main(int argc, char **argv)
{
  vector<string> v;
  for (int i = 1; i<argc; ++i)
    v.push_back(argv[i]);
  mt19937 g(static_cast<uint32_t>(time(0)));
  shuffle(v.begin(), v.end(), g);
  for (auto &x : v)
    cout << x << ' ';
  cout << '\n';
}
Run Code Online (Sandbox Code Playgroud)

(对于GCC 4.8.2,你需要编译它g++ -std=c++11 -Wall -g shuffle.cc -o shuffle)

在上面的示例中,PRNG以当前系统时间播种.

对于预C++ 11编译器,您只random_shuffle在STL中使用算法 - 但即使这样,您也可以选择为其指定数字生成器对象/函数.请注意,您不能只是插入PRNG对象mtl19937(因为它不提供operator()(U upper_bound)成员).

因此,您可以像这样提供自己的适配器:

#include <iostream>
#include <random>
#include <algorithm>
#include <vector>
#include <string>
#include <ctime>
using namespace std;

struct Gen {
  mt19937 g;
  Gen()
   : g(static_cast<uint32_t>(time(0)))
  {
  }
  size_t operator()(size_t n)
  {
    std::uniform_int_distribution<size_t> d(0, n ? n-1 : 0);
    return d(g);
  }
};

int main(int argc, char **argv)
{
  vector<string> v;
  for (int i = 1; i<argc; ++i)
    v.push_back(argv[i]);
  random_shuffle(v.begin(), v.end(), Gen());
  for (vector<string>::const_iterator i = v.begin(); i != v.end(); ++i)
    cout << *i << ' ';
  cout << '\n';
}
Run Code Online (Sandbox Code Playgroud)