[英]Can I clear default_random_engine generator after each use?
[英]Can I use a single `default_random_engine` to create multiple normally distributed sets of numbers?
我想生成一組單位矢量(對於任意尺寸),這些單位矢量在所有方向上均勻分布。 為此,我為每個矢量分量生成正態分布的數字,並按幅度的倒數來縮放結果。
我的問題 :我可以使用單個std::default_random_engine
為矢量的所有分量生成數字,還是每個分量都需要自己的引擎?
Afaik,每個部分都需要獨立分配高斯分布,以便數學計算出來,而我無法評估這兩種情況之間的差異。 這是具有單個RNG的MWE(此處省略了向量的分配和規范化)。
std::vector<std::vector<double>> GenerateUnitVecs(size_t dimension, size_t count)
{
std::vector<std::vector<double>> result;
/* Set up a _single_ RNG */
size_t seed = GetSeed(); // system_clock
std::default_random_engine gen(seed);
std::normal_distribution<double> distribution(0.0, 1.0);
/* Generate _multiple_ (independent?) distributions */
for(size_t ii = 0; ii < count; ++ii){
std::vector<double> vec;
for(size_t comp = 0; comp < dimension; ++comp)
vec.push_back(distribution(gen)); // <-- random number goes here
result.push_back(vec);
}
return result;
}
謝謝。
我假設您不是並行生成隨機數。 從理論上講,用一個引擎生成隨機獨立的高斯矢量沒有問題。
對std::normal_distribution
的()
運算符的每次調用std::normal_distribution
按照指定的高斯分布為您提供一個隨機的實數值。 ()
運算符的連續調用為您提供了獨立的樣本。 在gcc
(我的版本: 4.8
)中的實現使用Marsaglia Polar方法生成標准的正常隨機數。 您可以閱讀此 Wikipedia頁面以獲取更多詳細信息。
但是,對於需要高質量隨機性和大量隨機樣本的嚴格科學研究,我建議使用Mersenne-Twister引擎 ( mt19937
32位或64位)而不是默認引擎,因為它基於a完善的方法,周期長,在統計隨機檢驗中表現良好。
OP問:
我的問題:我可以使用單個std :: default_random_engine為向量的所有分量生成數字,還是每個分量都需要自己的引擎?
我建議像其他人在評論中所述,關於不使用std::default_random_engine
而不是使用std::random_device
或std::chrono::high_resolution_clock
std::random_device
要將random_device
用於normal distribution
或Gaussian
normal distribution
,這非常簡單:
#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::setw(2)
<< p.first << ' ' << std::string(p.second/200, '*' ) << '\n';
}
}
要使用std::chrono::high_resolution_clock
:還有更多工作,但同樣簡單。
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>
#include <cmath>
#include <limits>
#include <chrono>
class ChronoClock {
public:
using Clock = std::conditional_t<std::chrono::high_resolution_clock::is_steady,
std::chrono::high_resolution_clock,
std::chrono::steady_clock>;
static unsigned int getTimeNow() {
unsigned int now = static_cast<unsigned int>(Clock::now().time_since_epoch().count());
return now;
}
};
int main() {
/*static*/ std::mt19937 gen{}; // Can be either static or not.
gen.seed( ChronoClock::getTimeNow() );
// 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::setw(2)
<< p.first << ' ' << std::string(p.second/200, '*' ) << '\n';
}
}
從上面的示例中可以看到,這些示例在 cppreference.com
上顯示,它們具有單個引擎,單個種子和單個分發,它使用單個引擎生成隨機數或隨機數集。
編輯 - 另外,您可以將我作為封裝類編寫的類用於random engines
和random distributions
。 您可以在這里參考我的答案。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.