c++的random_shuffle总是给出相同的结果

C++ random_shuffle is always giving the same results

本文关键字:结果 random shuffle c++      更新时间:2023-10-16

下面对随机洗牌的调用总是对向量v

给出相同的结果
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstdlib>
using namespace std;
int main(){
  vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  srand(time(0));
  random_shuffle(v.begin(), v.end());
  for (int i = 0; i < v.size(); ++i) printf("%d ", v[i]); printf("n");
  printf("%dn", rand() % 100);
  return 0;
}

我试过用

编译
g++ -std=c++0x
g++ -std=c++11

但两者每次都给出相同的结果,所以我真的不明白是怎么回事。

$./a.out
7 1 4 6 8 9 5 2 3 10 
26
$ ./a.out
7 1 4 6 8 9 5 2 3 10 
41
$ ./a.out
7 1 4 6 8 9 5 2 3 10 
39

OP的评论清楚地表明他们使用的是Clang和libc++,而不是GCC/libstdc++。

快速查看libc++的random_shuffle实现,可以看出它使用__rs_default类型的对象作为其随机性的来源,检查__rs_default的实现可以看出它只是使用默认构造的std::mt19937对象:

__rs_default::result_type
__rs_default::operator()()
{
    static mt19937 __rs_g;
    return __rs_g();
}

换句话说,在这个实现中,srandrandom_shuffle的双参数版本所使用的"随机性"来源没有任何影响。(吓人的引号是因为它总是使用一个固定的种子。)注意,random_shuffle根本不需要使用rand,所以你不能指望srand在可移植代码中"工作"。

使用std::shuffle<random>设施。

首先,-std=c++0x-std=c++11表示完全相同,所以测试它们是没有意义的。

你没有提供一个完整的程序(请阅读https://stackoverflow.com/help/mcve下次),所以我猜剩下的代码,我试着这样做:

#include <iostream>
#include <vector>
#include <algorithm>
#include <stdlib.h>
using namespace std;
int main()
{
  vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
  srand(time(0));
  random_shuffle(v.begin(), v.end());
  for (int i : v)
    std::cout << i << ' ';
  std::cout << std::endl;
}

我每秒钟得到不同的结果:

tmp$ ./a.out
2 1 8 5 9 7 6 3 10 4 
tmp$ ./a.out
10 7 6 3 1 8 9 4 5 2 
tmp$ ./a.out
4 7 3 6 5 8 1 9 10 2 
tmp$ ./a.out
4 7 3 6 5 8 1 9 10 2 
tmp$ ./a.out
4 7 3 6 5 8 1 9 10 2 
tmp$ ./a.out
10 2 6 3 9 4 5 7 8 1 
tmp$ ./a.out
10 2 6 3 9 4 5 7 8 1 
tmp$ ./a.out
10 2 6 3 9 4 5 7 8 1 
tmp$ ./a.out
2 1 3 7 5 8 9 6 4 10 

产生相同结果的次数是因为time(0)返回的秒数是相同的,因此rand()函数的种子是相同的,因此结果是相同的。如果您等待一秒钟,以便time(0)返回不同的值,您应该得到元素的不同随机洗牌。

如果你运行的代码和我的不一样,你可能会得到不同的结果,但我们无法解释结果,因为你没有给我们看你的代码。