正确的地方调用`std :: default_random_engine generator`

时间:2013-12-15 03:42:08

标签: c++

需要为数组生成随机排列序列。当然,我们可以使用专门为此目的设计的STL功能,但我想手动完成如下操作:

问题>根据代码,在我看来,我们不应该在循环中放置std::default_random_engine generator;。作为一般规则是真的吗?

// uniform_int_distribution
#include <iostream>
#include <random>
#include <utility>

void test1() // random result
{  
  int p[10]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  std::default_random_engine generator;
  for (int i=0; i<=9; ++i) {    
    std::uniform_int_distribution<int> distribution(i,9);  
    int index = distribution(generator);
    std::swap(p[index], p[i]);
    std::cout << i << ": " << p[i] << std::endl;
  }
}

void test2() // NOT random
{  
  int p[10]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9};  
  for (int i=0; i<=9; ++i) {    
    std::default_random_engine generator;
    std::uniform_int_distribution<int> distribution(i,9);  
    int index = distribution(generator);
    std::swap(p[index], p[i]);
    std::cout << i << ": " << p[i] << std::endl;
  }
}


int main()
{
    test1();
    std::cout << "*****************" << std::endl;
    test2();
    return 0;
}

/* output
0: 0
1: 2
2: 8
3: 6
4: 7
5: 3
6: 5
7: 9
8: 4
9: 1
*****************
0: 0
1: 1
2: 2
3: 3
4: 4
5: 5
6: 6
7: 7
8: 8
9: 9

*/

1 个答案:

答案 0 :(得分:2)

随机生成器引擎在进入范围时会被播种。

在你的第一个函数中,你有这个基本结构:

void test1() // random result
{  
  std::default_random_engine generator;
  for (int i=0; i<=9; ++i) {    
      // ...
  }
}

当您输入test1()时,随机数生成器会播种。每当你拨打test1()时,你都会得到一个新的发电机,很可能是相同的排列。该生成器的范围是从声明点到test1()的右括号。

在你的第二个函数中,你有这个替代结构:

void test2() // NOT random
{  
  for (int i=0; i<=9; ++i) {    
    std::default_random_engine generator;

    // ...
  }
}

此生成器在循环的每次迭代开始时进入范围,并在每次迭代结束时(在循环增量之前)超出范围。我相信,这将在每次迭代时为您提供相同的随机数序列。

如果你想要一个接种一次的随机序列,你需要只有一个生成器实例。要么使它成为全局变量,要么将对引擎的引用作为函数的参数传递。