2012-12-23 46 views
18

Tôi cần tạo số ngẫu nhiên, nhưng từ phạm vi rộng nhất có thể (ít nhất 64 bit). Tôi không quan tâm liệu phân phối có hoàn hảo hay không, do đó, std::rand() sẽ hoạt động nhưng chỉ trả lại int. Tôi hiểu rằng C++ 11 có một số khả năng tạo số ngẫu nhiên có thể cung cấp bất kỳ số kích thước nào, nhưng rất phức tạp để sử dụng. Ai đó có thể đăng một ví dụ đơn giản về cách sử dụng nó đơn giản nhất có thể để có được chức năng được mô tả (64 bit hoặc nhiều số ngẫu nhiên) theo cách đơn giản nhất có thể (như std::rand())?C++ 11 số ngẫu nhiên

Trả lời

30

Đây là cách sử dụng C++ 11 thế hệ số ngẫu nhiên cho mục đích này (điều chỉnh từ http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution):

#include <random> 
#include <iostream> 
int main() 
{ 
    /* Initialise. Do this once (not for every 
    random number). */ 
    std::random_device rd; 
    std::mt19937_64 gen(rd()); 

    /* This is where you define the number generator for unsigned long long: */ 
    std::uniform_int_distribution<unsigned long long> dis; 

    /* A few random numbers: */  
    for (int n=0; n<10; ++n) 
    std::cout << dis(gen) << ' '; 
    std::cout << std::endl; 
    return 0; 
} 

Thay vì unsigned long long, bạn có thể sử dụng std::uintmax_t từ cstdint để có phạm vi số nguyên lớn nhất có thể (không sử dụng thư viện số nguyên lớn thực).

+1

Điều này là rất tốt cho gần như tất cả sử dụng, nhưng lưu ý rằng nó chỉ cung cấp 'byteof (unsigned)' byte của entropy cho hạt giống. Nếu bạn cần nhiều hơn, có thể chuyển một ['std :: seed_seq'] (http://en.cppreference.com/w/cpp/numeric/random/seed_seq) vào hàm tạo của' mt19937' để vượt qua như nhiều byte ngẫu nhiên như bạn muốn. –

4

Không C++ 11, nhưng dễ dàng đủ

((unsigned long long)rand() << 32) + rand() Ở đây chúng ta tạo ra hai bộ phận của Int64 như int32 của

Như JasonD chỉ ra, nó giả định rằng rand() tạo 32bit số nguyên. Có thể xor rand() << x, rand() << (2*x), rand() << (3*x), v.v., trong đó x < = bit được tạo bằng rand() số`. Nó cũng sẽ ổn thôi.

+12

Giả sử rand() thực sự trả lại số 32 bit. Nó có khả năng chỉ 31-bit, nếu nó không phải là 15-bit. – JasonD

+1

@JasonD Có, @RiaD nên kiểm tra 'RAND_MAX' để xác định điều này. –

+0

Dưới Microsoft cl, lên đến 19.x hiện tại, 'RAND_MAX' là 0x7FFF hoặc 15 bit. – kkm

12

Chúng ta có thể dễ dàng quấn động cơ máy phát điện số ngẫu nhiên vào/phương pháp rand-như srand như thế này:

#include <random> 
#include <iostream> 

struct MT19937 { 
private: 
    static std::mt19937_64 rng; 
public: 
    // This is equivalent to srand(). 
    static void seed(uint64_t new_seed = std::mt19937_64::default_seed) { 
     rng.seed(new_seed); 
    } 

    // This is equivalent to rand(). 
    static uint64_t get() { 
     return rng(); 
    } 
}; 

std::mt19937_64 MT19937::rng; 


int main() { 
    MT19937::seed(/*put your seed here*/); 

    for (int i = 0; i < 10; ++ i) 
     std::cout << MT19937::get() << std::endl; 
} 

(Giống như srandrand, triển khai này không quan tâm đến thread-an toàn.)

Các chức năng của trình bao bọc cũng không đáng kể đến mức bạn chỉ có thể sử dụng động cơ trực tiếp.

#include <random> 
#include <iostream> 

static std::mt19937_64 rng; 

int main() { 
    rng.seed(/*put your seed here*/); 

    for (int i = 0; i < 10; ++ i) 
     std::cout << rng() << std::endl; 
} 
+2

Thật không may, 'std :: mt19937_64 :: default_seed' được chuẩn hóa là '5489u', vì vậy các chương trình mẫu của bạn sẽ luôn tạo ra cùng một chuỗi đầu ra. –

+4

@JeffreyYasskin: Có. Cũng giống như trong 'srand()', bạn cần cung cấp hạt giống của riêng bạn để có được một chuỗi ngẫu nhiên riêng biệt. – kennytm