2012-05-22 23 views
10

Có chức năng nào để thu thập thống nhất số nguyên giả ngẫu nhiên được phân phối trong một số phạm vi được chỉ định không? Tôi có thể viết chức năng của riêng tôi bằng cách sử dụng rand, nhưng điều này có vẻ như một tình huống đủ phổ biến mà có lẽ một cái gì đó trong STL cho nó.Cách tiêu chuẩn để nhận các số nguyên ngẫu nhiên được phân bố đều trong C++ là gì?

Trả lời

15

Boost cung cấp nhiều công cụ để tạo số ngẫu nhiên. Đối với phân phối đều liên tục bạn có điều này một:

http://www.boost.org/doc/libs/1_49_0/doc/html/boost/random/uniform_real_distribution.html

EDIT: cập nhật để bao gồm các mới C++ thực hiện 11. Đối với trường hợp số nguyên, ở đây bạn có tài liệu tham khảo:

http://en.cppreference.com/w/cpp/numeric/random/uniform_int_distribution

Một ví dụ đơn giản sẽ là:

#include <random> 
#include <iostream> 
int main() 
{ 
    std::random_device rd; 
    std::mt19937 gen(rd()); 
    std::uniform_int_distribution<> dis(1, 6); 
    for(int n=0; n<10; ++n) 
     std::cout << dis(gen) << ' '; 
    std::cout << '\n'; 
} 
+5

Và bây giờ họ là một phần của ** C++ 11 ** do đó họ là tiêu chuẩn. –

+0

@ K-ballo thật tuyệt! C++ 11 làm cho C++ dễ dàng hơn nhiều :) – betabandido

+1

Có thể một ví dụ mã nhỏ có thể hữu ích. – authchir

10

Để tạo số giả ngẫu nhiên trong C++, một lựa chọn rất tốt là sử dụng Mersenne twister động cơ máy phát số giả ngẫu nhiên: std::mt19937 từ tiêu đề <random>.

Chúng tôi có thể nghĩ đến động cơ này như một hộp đen mà spits ra chất lượng cao bit ngẫu nhiên.

Sau đó, các bit ngẫu nhiên này có thể là có hình dạng trong một số đầu ra số nguyên sử dụng phân phối ; đặc biệt, để có được phân phối thống nhất số giả ngẫu nhiên, một std::uniform_int_distribution có thể được sử dụng.

Lưu ý rằng đối tượng động cơ phải được khởi tạo với hạt giống .
std::random_device có thể được sử dụng cho mục đích đó.

Vì vậy, quá trình này có thể được tóm tắt trong ba bước logic:

  1. Tạo một thể hiện của std::random_device, để có được một hạt không xác định cho động cơ Mersenne twister.
  2. Tạo một thể hiện của std::mt19937engine, để nhận các bit giả ngẫu nhiên chất lượng cao.
  3. Sử dụng std::uniform_int_distribution đến hình dạng các bit ngẫu nhiên này trong số nguyên phân bố đồng đều.

compilable C++ sau:

#include <iostream>  // for console output 
#include <random>  // for pseudo-random number generators and distributions 

int main() 
{ 
    // Use random_device to generate a seed for Mersenne twister engine. 
    std::random_device rd;  

    // Use Mersenne twister engine to generate pseudo-random numbers. 
    std::mt19937 engine(rd()); 

    // "Filter" MT engine's output to generate pseudo-random integer values, 
    // **uniformly distributed** on the closed interval [0, 99]. 
    // (Note that the range is [inclusive, inclusive].) 
    std::uniform_int_distribution<int> dist(0, 99); 

    // Generate and print 10 pseudo-random integers 
    for (int i = 0; i < 10; ++i) 
    { 
     std::cout << dist(engine) << ' '; 
    } 
    std::cout << std::endl; 
} 

Để biết thêm chi tiết về tạo số giả ngẫu nhiên trong C++ (bao gồm cả lý do tại sao rand()không tốt), xem video này bởi Stephan T. Lavavej (từ Going Native 2013):

rand() Considered Harmful

+0

+1 Phải mất một lúc nhưng điều này cuối cùng đã được sáp nhập. Bạn có thể muốn chỉnh sửa câu hỏi của mình để cho biết rằng đó là một phần của hợp nhất và nhận xét cho OP cũng vì vậy họ hiểu tại sao câu trả lời mới này xuất hiện với một ngày cũ. –

+0

Tôi không biết tại sao mọi người lại nói rằng Mersenne Twister thật tuyệt vời và "chất lượng cao". Nó không phải. Nó là phức tạp, có một dấu chân bộ nhớ khổng lồ và vẫn thất bại nhiều bài kiểm tra của bộ testU01 BigCrush. Có một số PRNG đơn giản hơn, nhanh hơn và có chất lượng cao hơn hiện nay với thời gian thích hợp. – plasmacel

+0

@plasmacel: Tôi đã hỏi Stephan T. Lavavej (người bảo trì VC STL) và ông đã xác nhận PRNG tiêu chuẩn tốt nhất của nó. Những gì bạn sẽ đề xuất như là lựa chọn thay thế tốt hơn? –

0

Để tạo một hoặc số quy định của các biến ngẫu nhiên với phân bố đồng đều trên tên miền số nguyên sử dụng std::generate_nboost:

#include <iostream> 
#include <algorithm> 
#include <boost/random.hpp> 

/* 
* 
*/ 
int main(int argc, char** argv) { 
    boost::mt19937 rand_generator(std::time(NULL)); 
    boost::random::uniform_int_distribution<> int_distribution(0, 100); 

    //Need to pass generator 
    std::cout << int_distribution(rand_generator) << std::endl; 

    //Associate generator with distribution 
    boost::random::variate_generator<boost::mt19937&, 
      boost::random::uniform_int_distribution<> 
      > int_variate_generator(rand_generator, int_distribution); 

    //No longer need to pass generator 
    std::cout << int_variate_generator() << std::endl; 
    std::generate_n(std::ostream_iterator<int>(std::cout, ","), 3, int_variate_generator); 
    return 0; 
} 
Các vấn đề liên quan