C++11 隨機數


C++11帶來諸多特性,random就是其一.

隨機數由生成器和分布器結合產生

  生成器generator:能夠產生離散的等可能分布數值(需要種子,不然每次生存的隨機數都一樣)
  分布器distributions: 能夠把generator產生的均勻分布值映射到其他常見分布,如均勻分布uniform,正態分布normal,二項分布binomial,泊松分布poisson
  種子:相當於外部傳給隨機數生成器的誘因,如果每次傳入的種子一樣,則每次生成的隨機數還是一樣
 
1.default_random_engine 
//std::default_random_engine engine();  //沒有設置種子,每次生存的隨機數都一樣
std::default_random_engine engine(time(nullptr));  //設置了種子,每次種子都不一樣
std::uniform_int_distribution<> dis(1, 10);
for (int n = 0; n < 10; n++)
    std::cout << dis(engine) << " " << std::endl;
注:default_random_engine 結合uniform_int_distribution生成的隨機數是閉環[begin, end]
如果嫌每次調用都要傳入generator對象麻煩,可以使用std::bind,要包含頭文件functional,以后就可以直接調用dice()產生復合均勻分布的隨機數。
//std::default_random_engine engine();  //沒有設置種子,每次生存的隨機數都一樣
std::default_random_engine engine(time(nullptr));
std::uniform_int_distribution<> dis(1, 10);
auto dice = std::bind(dis,generator);
for (int n = 0; n < 10; n++) std::cout << dice() << " " << std::endl;

 

2. random_device

  標准庫提供了一個非確定性隨機數生成設備.在Linux的實現中,是讀取/dev/urandom設備;Windows的實現居然是用rand_s,在這里強烈譴責一下.

  random_device提供()操作符,用來返回一個min()到max()之間的一個數字.如果是Linux(Unix Like或者Unix)下,都可以使用這個來產生高質量的隨機數,可以理解為真隨機數.

#include <iostream>
#include <random>
int main()
{
  std::random_device rd;
  for(int n=0; n<20000; ++n)
    std::cout << rd() << std::endl;
  return 0; 
}

//結合:default_random_engine使用生成指定范圍內的真隨機數
int main()
{
    std::random_device rd; 
    std::default_random_engine engine(rd());
    std::uniform_int_distribution<> dis(10, 20); 
    auto dice = std::bind(dis, engine); 
    for (int n = 0; n < 10; n++) 
        std::cout << dice() << " " << std::endl;
 }

 

2. random number engine

  標准把隨機數抽象成隨機數引擎和分布兩部分.引擎用來產生隨機數,分布產生特定分布的隨機數(比如平均分布,正太分布等).

  標准提供三種常用的引擎:linear_congruential_engine,mersenne_twister_engine和subtract_with_carry_engine.第一種是線性同余算法,第二種是梅森旋轉算法,第三種帶進位的線性同余算法.第一種是最常用的,而且速度也是非常快的; 第二種號稱是最好的偽隨機數生成器;第三種沒用過....

  隨機數引擎接受一個整形參數當作種子,不提供的話,會使用默認值. 推薦使用random_device來產生一個隨機數當作種子.(windows下愛咋整咋整,誰叫windows的random_device是調用rand_s)

#include <iostream>
#include <random>

int main()
{
    std::random_device rd;
    std::mt19937 mt(rd());
    for(int n = 0; n < 10; n++)
        std::cout << mt() << std::endl;
    return 0;
}

3. random number distributions

  標准提供各種各樣的分布,不過我們經常用的比較少,比如平均分布,正太分布...使用也很簡單

//平均分布
#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';
}

//正太分布
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>
#include <cmath>
int main()
{
    std::random_device rd;
    std::mt19937 gen(rd());
 
    // values near the mean are the most likely
    // standard deviation affects the dispersion of generated values from the mean
    std::normal_distribution<> d(5,2);
 
    std::map<int, int> hist;
    for(int n=0; n<10000; ++n) {
        ++hist[std::round(d(gen))];
    }
    for(auto p : hist) {
        std::cout << std::fixed << std::setprecision(1) << std::setw(2)
                  << p.first << ' ' << std::string(p.second/200, '*') << '\n';
    }
}
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM