【问题标题】:C++ random_shuffle is always giving the same resultsC++ random_shuffle 总是给出相同的结果
【发布时间】:2016-10-04 21:03:11
【问题描述】:

以下对随机洗牌的调用总是为向量 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("%d\n", 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

【问题讨论】:

  • 您在哪里/何时致电srand(time(0));?你是如何测试的?
  • 欢迎使用stackoverflow,请在询问“为什么这段代码不起作用?”时提供一个完整程序所以我们不必浪费时间添加您面前已经存在的缺失代码。
  • @AnaEchavarria 它总是为我生成不同的结果。但是,如果在同一秒内启动,它必须始终生成相同的结果。
  • 这是clang/libc++。他们的random_shuffle 不使用rand 作为随机源。

标签: c++ c++11


【解决方案1】:

OP's comment 明确表示这是他们使用的 Clang 和 libc++,而不是 GCC/libstdc++。

快速浏览一下 libc++ 的 random_shuffle implementation 会发现它使用 __rs_default 类型的对象作为随机源,检查 the implementation of __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&lt;random&gt; 设施。

【讨论】:

  • 如果 &lt;random&gt; 出于某种原因(老师等)应该被禁止,你可以通过调用 std::random_shuffle time() 来解决这个问题(也许是 mod smth。如果需要很长时间,没有测试)次。不过,这确实是一个 hack,尽可能使用 &lt;random&gt; 的东西,正如 TC 所说。
【解决方案2】:

首先,-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) 返回不同的值,您应该会得到不同的随机元素随机播放。

如果您运行的代码与我的不同,您可能会得到不同的结果,但我们无法解释结果,因为您没有向我们展示您的代码。

【讨论】:

  • 谢谢乔纳森。我已更新问题以包含整个代码。我等待超过一秒钟重新运行它,但仍然得到相同的结果。我知道srand(time(0)) 正在工作,因为如果我添加一个like 来打印rand() 的值,它每次都会产生不同的结果。只是random_shuffle 产生了相同的结果。
猜你喜欢
  • 1970-01-01
  • 2011-10-19
  • 1970-01-01
  • 2011-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多