C/C++中如何產生偽隨機數

來源:互聯網
上載者:User

標籤:

  本文主要參考自一博文及cplusplus和cppreferrence。其中,該博文是對cplusplus上該偽隨機數條目的翻譯,下文中會參考調整。

  1. C語言中的偽隨機數產生函數

 

  2. C++語言中的偽隨機數產生器

  C++中偽隨機數庫Random是C++11才開始添加的。它允許我們結合產生器(Generators)和分布器(Distributions)來產生偽隨機數。 

   產生器(Generators):能夠產生離散的等可能分布數值。   分布器(Distributions): 能夠把產生器產生的均勻分布值映射到其他各種各樣的分布,如均勻分布uniform,常態分佈normal,二項分布binomial,泊松分布poisson。   2.1 一個簡單的例子  下邊就是一個簡單的例子:
 1 #include <iostream> 2 #include <random> 3 using namespace std; 4  5 int main() 6 { 7     default_random_engine generator; 8     uniform_int_distribution<int> dis(0, 6); 9     for (int i = 0; i < 6; i++)10     {11         std::cout << dis(generator) << std::endl;    // 1 0 1 1 2 612     }13 14     return 0;15 }
View Code

  如果我們嫌每次都要傳入產生器對象麻煩,我們可以使用std::bind來綁定產生器對象和分布器對象(注意bind在標頭檔functional中)。如下所示:

 1 #include <iostream> 2 #include <random> 3 #include <functional>    // std::bind 4 using namespace std; 5  6 int main() 7 { 8     default_random_engine generator; 9     uniform_int_distribution<int> dis(0, 6);10     auto dice = bind(dis, generator);11     for (int i = 0; i < 6; i++)12     {13         std::cout << dice() << std::endl;    // 1 0 1 1 2 614     }15 16     return 0;17 }
View Code

  其實我們會發現上邊兩個代碼的結果不管跑多少次都是一樣的,很奇怪!我們可以試著給產生器一個種子,如下:

 1 #include <iostream> 2 #include <random> 3 #include <functional>    // std::bind 4 using namespace std; 5  6 int main() 7 { 8     default_random_engine generator(10);    // seed = 10 9     uniform_int_distribution<int> dis(0, 6);10     auto dice = bind(dis, generator);11     for (int i = 0; i < 6; i++)12     {13         std::cout << dice() << std::endl;    // 2 0 4 1 2 414     }15 16     return 0;17 }
View Code

  現在我們看到結果不一樣了。但是,不管我們再跑多少次,其結果還是一樣的,這就更加奇怪了。究其原因,在於我們設定的種子是固定的。對於電腦而言,當輸入確定時,輸出也一定是確定的。因為產生器演算法和分布器演算法都是確定的,所以當輸入是確定的時候,輸出也必然是確定的。因此,為了得到不一樣的結果,我們可以將系統時間當作種子:

 1 #include <iostream> 2 #include <random> 3 #include <functional>    // std::bind 4 #include "time.h"        // time 5 using namespace std; 6  7 int main() 8 { 9     default_random_engine generator(time(NULL));10     uniform_int_distribution<int> dis(0, 6);11     auto dice = bind(dis, generator);12     for (int i = 0; i < 6; i++)13     {14         std::cout << dice() << std::endl;15     }16 17     return 0;18 }
View Code   2.2 關於產生器和分布器

  關於產生器和分布器,請參照cplusplus手冊。

  下邊是一個來自cppreferrence的例子:
 1 #include <iostream> 2 #include <iomanip> 3 #include <string> 4 #include <map> 5 #include <random> 6 #include <cmath> 7 using namespace std; 8  9 int main()10 {11     // Seed with a real random value, if available12     std::random_device rd;13     cout << rd() << endl;14     // Choose a random mean between 1 and 615     std::default_random_engine e1(rd());16     std::uniform_int_distribution<int> uniform_dist(1, 6);17     int mean = uniform_dist(e1);18     std::cout << "Randomly-chosen mean: " << mean << ‘\n‘;19 20     // Generate a normal distribution around that mean21     std::mt19937 e2(rd());22     std::normal_distribution<> normal_dist(mean, 2);    // default: double23 24     std::map<int, int> hist;25     for (int n = 0; n < 10000; ++n) {26         ++hist[std::round(normal_dist(e2))];27     }28     std::cout << "Normal distribution around " << mean << ":\n";29     for (auto p : hist) {30         std::cout << std::fixed << std::setprecision(1) << std::setw(2)31             << p.first << ‘ ‘ << std::string(p.second / 200, ‘*‘) << ‘\n‘;32     }33 34     return 0;35 }
View Code

  我們可以發現上述例子用到了random_device這個產生器。該產生器產生的是非確定性隨機數。在Linux的實現中,是讀取/dev/urandom裝置;在Windows的實現居然是用rand_s。random_device提供()操作符,用來返回一個min()到max()之間的一個數字(min()、max()均為該產生器成員函數)。如果是Linux(Unix Like或者Unix)下,都可以使用這個來產生高品質的隨機數,可以理解為真隨機數。

  一個例子如下:
 1 // random_device example 2 #include <iostream> 3 #include <random> 4  5 int main () 6 { 7   std::random_device rd; 8  9   std::cout << "default random_device characteristics:" << std::endl;10   std::cout << "minimum: " << rd.min() << std::endl;11   std::cout << "maximum: " << rd.max() << std::endl;12   std::cout << "entropy: " << rd.entropy() << std::endl;13   std::cout << "a random number: " << rd() << std::endl;14 15   return 0;16 }
View Code

  可能的輸出是:

1 default random_device characteristics:2 minimum: 03 maximum: 42949672954 entropy: 325 a random number: 4230014324
View Code

  有些情況下,隨了拿時間當種子,random_device也經常被用來產生種子。

 

C/C++中如何產生偽隨機數

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.