新的C++ 11標準有一整章專用於隨機數生成器。但這樣做我怎麼執行用於編碼這樣最簡單,最常見的任務,但沒有訴諸標準C庫:如何使用C++ 11標準庫生成一個隨機數
srand((unsigned int)time(0)); int i = rand();
是否有隨機數的發動機,分佈和種子合理的默認值是人們可以使用現成的盒子?
新的C++ 11標準有一整章專用於隨機數生成器。但這樣做我怎麼執行用於編碼這樣最簡單,最常見的任務,但沒有訴諸標準C庫:如何使用C++ 11標準庫生成一個隨機數
srand((unsigned int)time(0)); int i = rand();
是否有隨機數的發動機,分佈和種子合理的默認值是人們可以使用現成的盒子?
你應該能夠做這樣的事情:
std::default_random_engine e((unsigned int)time(0));
int i = e();
的default_random_engine
的質量依賴於實現。您也可以使用std::min_rand0
或std::min_rand
。
也許一種更好的種子隨機引擎的方法是使用真實的隨機數,而不是使用time
。
E.g.
爲了澄清,你的意思是「應該」,如「這不存在但它應該」或sd「存在並且你的編譯器應該支持它」? – GManNickG
信息:這個答案和OP的例子最大的區別在於編碼器控制引擎狀態的位置:它在'e'中。在OP的代碼中,狀態被隱藏爲'rand'內的靜態數據。這是處理多線程程序時的一個重要區別。 'rand'必須具有某種保護才能保證線程安全。 'default_random_engine'不。如果你想從多個線程中調用它,你可以在外部自己提供同步機制。這意味着'default_random_engine'可以更快,如果你不需要同步它。 –
@GMan:這意味着我目前唯一可以訪問的實現不支持它,所以我沒有能夠測試我的代碼;)。 –
如果你的現有代碼的新標準之前是適當的,那麼它將繼續。新的隨機數發生器被添加用於需要更高質量的僞隨機性的應用,例如,隨機模擬。
隨機數字的產生是一個難題。沒有真正的隨機的方式來做到這一點。如果你只是隨機產生一個遊戲環境,那麼你的方法應該沒問題。 rand()有幾個缺點。
如果您需要隨機性來生成加密密鑰,那麼您是S.O.L.在這種情況下,最好的辦法是去操作系統,通常有機制。在隨機()的POSIX上(或者如果你這麼處理,可以從/ dev/random中讀取)。在Windows中可以使用的CryptoAPI:
你可以使用RC4來生成隨機字節。這可能有你想要的屬性。這是快速和相當簡單的實施。當種子已知時,序列在所有實現中都是可重複的,而當種子未知時,序列是完全不可預知的。 http://en.wikipedia.org/wiki/RC4
我在我的項目中使用下面的代碼。 '引擎'和'發行'可以是圖書館提供的內容之一。
#include <random>
#include <functional>
#include <iostream>
...
std::uniform_int_distribution<unsigned int> unif;
std::random_device rd;
std::mt19937 engine(rd());
std::function<unsigned int()> rnd = std::bind(unif, engine);
std::cout << rnd() << '\n';
統一和簡化一些已經提供我就總結到的樣本:
// Good random seed, good engine
auto rnd1 = std::mt19937(std::random_device{}());
// Good random seed, default engine
auto rnd2 = std::default_random_engine(std::random_device{}());
// like rnd1, but force distribution to int32_t range
auto rnd3 = std::bind(std::uniform_int_distribution<int32_t>{}, std::mt19937(std::random_device{}()));
// like rnd3, but force distribution across negative numbers as well
auto rnd4 = std::bind(std::uniform_int_distribution<int32_t>{std::numeric_limits<int32_t>::min(),std::numeric_limits<int32_t>::max()}, std::mt19937(std::random_device{}()));
然後我進行了一些測試,看看默認的樣子:
#include <random>
#include <functional>
#include <limits>
#include <iostream>
template<class Func>
void print_min_mean_max(Func f) {
typedef decltype(f()) ret_t;
ret_t min = std::numeric_limits<ret_t>::max(), max = std::numeric_limits<ret_t>::min();
uint64_t total = 0, count = 10000000;
for (uint64_t i = 0; i < count; ++i) {
auto res = f();
min = std::min(min,res);
max = std::max(max,res);
total += res;
}
std::cout << "min: " << min << " mean: " << (total/count) << " max: " << max << std::endl;
}
int main() {
auto rnd1 = std::mt19937(std::random_device{}());
auto rnd2 = std::default_random_engine(std::random_device{}());
auto rnd3 = std::bind(std::uniform_int_distribution<int32_t>{}, std::mt19937(std::random_device{}()));
auto rnd4 = std::bind(std::uniform_int_distribution<int32_t>{std::numeric_limits<int32_t>::min(),std::numeric_limits<int32_t>::max()}, std::mt19937(std::random_device{}()));
print_min_mean_max(rnd1);
print_min_mean_max(rnd2);
print_min_mean_max(rnd3);
print_min_mean_max(rnd4);
}
主要生產的輸出:
min: 234 mean: 2147328297 max: 4294966759
min: 349 mean: 1073305503 max: 2147483423
min: 601 mean: 1073779123 max: 2147483022
min: -2147481965 mean: 178496 max: 2147482978
因此,我們可以看到,mt19937和default_random_engine具有不同的默認範圍,因此建議使用uniform_int_distribution。
另外,即使在使用有符號整數類型時,uniform_int_distribution的默認值是[0,max_int](非負)。必須明確提供範圍,如果你想全範圍。
最後,its important to remember this有時喜歡這些。
值得注意的是,有一個64位版本的'std :: mt19937':'std :: mt19937_64',每個調用返回64位的隨機性。 'auto rnd5 = std :: mt19937_64(std :: random_device {}()); // min:4879020137534 mean:1655417118684 max:18446741225191893648' – Sean
順便說一下,重複使用與許多發行版和std :: bind()相同的隨機數引擎是否安全,還是更好地將每個發行版綁定到新的引擎實例?這是如何:'std :: mt19937_64 random = std :: mt19937_64(std :: random_device {}());''auto randomCardinality = std :: bind(std :: uniform_int_distribution
你在這裏。隨機雙打範圍:
// For ints
// replace _real_ with _int_,
// <double> with <int> and use integer constants
#include <random>
#include <iostream>
#include <ctime>
#include <algorithm>
#include <iterator>
int main()
{
std::default_random_engine rng(std::random_device{}());
std::uniform_real_distribution<double> dist(-100, 100); //(min, max)
//get one
const double random_num = dist(rng);
//or..
//print 10 of them, for fun.
std::generate_n(
std::ostream_iterator<double>(std::cout, "\n"),
10,
[&]{ return dist(rng);});
return 0;
}
維基百科? http://en.wikipedia.org/wiki/C%2B%2B0x#Extensible_random_number_facility – quasiverse
你的代碼有什麼問題? AFAIK,新的隨機數發生器被添加到更多「嚴重」的應用中,隨機數生成的方面真的很重要。 – GManNickG
@GMan:公平的說,新標準中的幾個隨機數引擎可以被描述爲簡單和快速,我不會認爲它們特別「嚴重」。 –