2012-06-21 103 views
2

我写了这个代码工作正常,但每次输出是相同的。所以没有任何随机的。好奇知道为什么! 假设:33名学生 第一行:7名学生 第二行:9名学生 第三行:9名学生 第4行:8名学生随机返回相同的输出每次

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

int main() { 
    vector<int> random; 

    for (int i = 1; i < 34; i++) 
     random.push_back(i); 

    random_shuffle(random.begin(), random.end()); 

    for (int i = 1; i < 8; i++) 
     cout << random[i] << " " ; 
    cout << endl; 

    int i = 7; 
    int num_seats = 1; 

    for (int j = 1; j <=3; j++) { 
     while (num_seats < 10 && i < 33) { 
     cout << random[i++] << " " ; 
     num_seats++; 
     } 
     cout << endl; 
     num_seats = 1; 
    } 
} 
+0

大家知道,C++ 11有一个['iota'](http://en.cppreference.com/w/cpp/algorithm/iota )功能,可以帮助您避免使用连续数字填充矢量。 – chris

+2

您是否向随机数生成器提供了[随机种子](http://en.wikipedia.org/wiki/Random_seed)? – Veger

回答

7

您需要首先初始化随机数发生器。随机数生成取决于“种子值”。要在每次执行程序时拥有唯一的种子值,您可以依赖当前时间。 time(NULL)返回表示当前时间的秒数 - 可以是唯一的种子。

尝试内部main()

srand(unsigned(time(NULL))); 
+0

是正确的,但是为什么他的“问题”首先存在的一点解释可能会有帮助 – ltjax

+0

@Itjax:在听起来像一个透视的风险,我敢打赌,这是课程的这个特定部分的重点是,教PRNG如何工作)。 –

+1

实际上并没有指定'random_shuffle'使用'rand()'作为随机的来源,所以这不一定是可移植的。 – bames53

2

在第一行中添加此使用的过载random_shuffle()访问随机性的未指定的源。它几乎肯定使用rand(),这意味着你需要使用srand()来播种它以获得不同的随机洗牌。

然而更便携的解决方案将是指定一个随机来源,因此您不必假设使用rand()。如果你的代码是C++ 11的话,最好的选择是使用shuffle()和发动机从<random>库:

#include <random> 
#include <algorithm> 

#include <vector> 
#include <numeric> 
#include <iterator> 
#include <iostream> 

int main() { 
    std::vector<int> v(34); 
    iota(begin(v), end(v), 1); 

    std::random_device r; 
    std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()}; 
    std::mt19937_64 eng(seed); 

    shuffle(begin(v), end(v), eng); 

    copy(begin(v), end(v), std::ostream_iterator<int>(std::cout, " ")); 
    std::cout << '\n'; 
} 

缺席C++ 11可以使用random_shuffle()重载需要一个随机数生成器,所以该程序可移植地指定了随机性的来源:

#include <cstdlib> 
#include <ctime> 
#include <algorithm> 

#include <vector> 
#include <iterator> 
#include <iostream> 

struct RNG { 
    int operator() (int n) { 
     return static_cast<int>(std::rand()/(static_cast<double>(RAND_MAX)+1) * n); 
    } 
}; 

int main() { 
    std::vector<int> v(34); 
    for (int i=0; i < v.size(); ++i) 
     v[i] = i + 1; 

    std::srand(std::time(NULL)); 
    random_shuffle(v.begin(), v.end(), RNG()); 

    copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " ")); 
    std::cout << '\n'; 
} 
+0

+1,但是如果你使用'C++ 11',为什么不使用'{}'来避免最烦人的解析而不是多余的'()'。它也保持'random_device'构造和调用之间的区别更清晰。 – KillianDS

+0

@KillianDS我认为,但是我决定让我的示例支持一些流行的编译器,它们还没有实现通用初始化语法,但是它们具有必要的C++ 11库组件。 – bames53

相关问题