2012-06-21 4 views
2

Я написал этот код, который работает нормально, но каждый раз вывод такой же. Так что ничего случайного об этом. Любопытно узнать почему! Предположение: 33 студентов Первого ряда: 7 студентов второго ряда: 9 студентов третьего ряда: 9 студентов четвёртых строк: 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'; 
} 

Absent 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

Смежные вопросы