C++11 隨機數生成器

  • 2020 年 9 月 22 日
  • 筆記

背景

考試想造浮點數然後發現不會
正好下午被虎哥茶話會
談到了一些不會的問題balabala的
被告知\(C++11\)有些神奇特性(哦豁)
然後就學習了一手看上去沒什麼用的隨機數生成器\(QwQ\)

函數

random_device

標準庫提供了一個非確定性隨機數生成設備
\(Linux\)的實現中,是讀取\(/dev/urandom\)設備
random_device提供()操作符,用來返回一個min()到max()之間的一個數字
如果是\(Linux(Unix Like或者Unix)\)下,都可以使用這個來產生高品質的隨機數,可以理解為真隨機數
(以上都是廢話,其實和最原始的c++的rand()用法一樣,不過真隨機數好評)

#include <iostream>
#include <random>
using namespace std;
signed main(){
	random_device rand;
   	cout << rand() << endl;
        return 0;
}

default_random_engine

一個隨機化的前置引擎
給後面要用到的函數生成一個隨機節點(時間戳balabala隨便理解一下就好,並沒有什麼卵用,就是讓後面的函數隨機化更強)
和上面提到的random_device不同的是,這個需要提供時間種子,看上去和rand也沒什麼區別。。。

#include <iostream>
#include <random>
using namespace std;
signed main(){
	default_random_engine rand(time(NULL));
   	cout << rand() << endl;
	return 0;
}

uniform_int_distribution

好了乾貨來了
該函數的作用是生成一個[a,b]範圍內的整數
定義的時候傳進去相應的參數(數據範圍即可)

uniform_int_distribution<int> rand1(-100, 100);

調用的時候給時間種子(就是上面device寫的rand函數)

cout << rand1(rand) << " ";

uniform_real_distribution

最有用的東西還是這個實數域的隨機生成器
用法和上述int一樣

uniform_real_distribution<double> rand2(0.0, 1.0);
cout << rand2(rand) << endl;

正態分布normal_distribution

再來說一個常用的
正態分布
正態分布\(N(μ,σ^2)\)呈現經典的」鐘形曲線」的形狀,其中中心峰的\(x\)坐標由\(μ\)給出,峰的寬度受\(σ\)控制。
正態分布由兩個參數控制,\(μ∈R\)\(σ∈(0,∞)\)
分布的標準差用\(σ\)表示,方差用\(σ^2\)表示
使用方法,第一個參數是\(μ\),第二個是\(σ\)

normal_distribution<double> N(10.0, 5.0);

為了方便直觀的看出數據分布,把每次生成的數據出現次數+1,測試的時候輸出了數據分布影像

for(register int i = 0; i < 10000; i++){
	      double num = nor(rand);
	      if ((num >= 0.0) && (num < 20.0)) ++p[int(num)];
	}
	for (int i = 0; i < 20; ++i) {
    	cout << i << "-" << (i + 1) << ": ";
    	cout << string(p[i] * 100 / 10000, '*') << endl;
}


具體要求按照具體題目要求,修改參數即可

Code

最後把程式碼粘貼一下,有需要自取就好

#include <iostream>
#include <random>
using namespace std;

int p[1000];

signed main(){
	default_random_engine rand(time(NULL));
	
	uniform_int_distribution<int> rand1(-100, 100);
	uniform_real_distribution<double> rand2(0.0, 1.0);
	cout << rand() << " ";
	cout << rand1(rand) << " ";
	cout << rand2(rand) << endl;
	
	normal_distribution<double> nor(10.0, 5.0);
	for(register int i = 0; i < 10000; i++){
		double num = nor(rand);
		if ((num >= 0.0) && (num < 20.0)) ++p[int(num)];
	}
	for (int i = 0; i < 20; ++i) {
    	cout << i << "-" << (i + 1) << ": ";
    	cout << std::string(p[i] * 100 / 10000, '*') << std::endl;
	}
	return 0;
}

小結

目前常用的這些
如果後續再有需求再補充吧
哦對了
編譯命令

g++ 001.cpp -std=c++11 -o 1