std::discrete_distribution<size_t> d{1, 1, 1, 1, 1, 3}/ // Six possible values std::random_device rd; std::default_random_engine rng {rd()}; std::map<size_t, size_t> results; // Store the results of throws for(size_t go {}; go < 5000; ++go) // 5000 throws of the die ++results[d(rng)]; for(const auto& pr : results) std::cout << "A" << (pr.first+1) << " was thrown " << pr.second << " timesn";建構函式的初始化列表包含 6 個權值,因此分布只會生成 [0,6) 這個範圍內的值,這意味著只包含從 1 到 5 的值。最後一個權值是其他權值的 3 倍,因此它出現的可能性是其他權值的 3 倍。執行這段程式碼會生成如下內容:
A 1 was thrown 607 times
A 2 was thrown 645 times
A 3 was thrown 637 times
A 4 was thrown 635 times
A 5 was thrown 617 times
A 6 was thrown 1859 times
std::discrete_distribution<size_t> d{20, 20, 20, 20, 20, 60};從 0 到 4,每個值的概率為 20/160,也就是 1/8,最後一個值的概率是 60/160 或 3/8。 也可以用序列指定權重。下面是使用相同的亂數生成器的第一個程式碼段的變化版:
std::array<double,6> wts {10.0, 10.0, 10.0, 10.0, 10.0, 30.0}; std::discrete_distribution<size_t> d{std::begin(wts), std::end(wts)}; std::array<string, 6> die_value {"one", "two", "three", "four", "five", "six"}; std::map<size_t, size_t> results; // Store the results of throws for(size_t go {}; go < 5000; ++go) // 5000 throws of the die ++results[d(rng)]; for(const auto& pr : results) std::cout << " A " << die_value [pr.first] << " was thrown " << pr.second << " timesn";這裡的權值是從陣列容器中得到的。分布物件生成的值被用來對陣列進行索引輸出。下面是得到的輸出:
A one was thrown 653 times
A two was thrown 601 times
A three was thrown 611 times
A four was thrown 670 times
A five was thrown 600 times
A six was thrown 1865 times
op(xmin + step/2), op(xmin + 3*step/2), op(xmin + 5*step/2),... op(xmin + (2*n-1)*step/2)數值的範例可以幫助說明發生了什麼。假設 n 是 6、xmin 是 0、xmax 是 12,因此步進值為 2。如果我們假設定義了使引數翻倍的 op,權重為 2、6、10、14、18、22,概率因此為 1/36、1/12、5/36、7/36、1/4、11/36。下面是這個分布物件的定義:
std::discrete_distribution<size_t> dist {6, 0, 12, [](double v) { return 2*v; }};一元運算子是由 lambda 表示式定義的,它會返回引數值的兩倍。可以通過呼叫 discrete_distribution 物件的成員函數 probabilities() 來獲取概率。對於 dist 物件可以按如下方式獲取概率:
auto probs = dist.probabilities(); // Returns type vector<double> std::copy(std::begin(probs), std::end(probs),std::ostream_iterator<double> { std::cout << std::fixed << std:: setprecision (2), " "}); std::cout << std::endl; // Output: 0.03 0.08 0.14 0.19 0.25 0.31通常,概率的個數是任意的,它和指定的權重的個數對應,因此這裡返回了一個 vector<double> 容器。注釋中顯示的輸出對應於先前展示的分數值。
dist.param({2, 2, 2, 3, 3}); // New set of weights auto parm = dist.param().probabilities(); std::copy(std::begin(parm), std::end(parm),std::ostream_iterator<double> {std::cout << std::fixed << std::setprecision (2)," "}); std::cout << std::endl; // Output: 0.17 0.17 0.17 0.25 0.25第一次呼叫 pamm() 成員函數時,它的引數是一個權重列表,這個列表中的值和原始值不同,值的個數超過之前的。呼叫無引數的 param() 版本會返回一個 param_type 物件,但是並不能準確地知道別名代表的型別是什麼。然而,我們知道它提供了和原始的分布物件相同的成員函數來存取引數。在這個範例中,意味著可以通過呼叫 param_type 物件的成員函數 probabilities() 來得到 param_type 物件中的值。這會返回一個 vector<double> 容器,然後就可以存取它。注釋顯示了它所包含的概率,並且可以看出它們是和新的權值對應的。