我想生成一组单位向量(适用于任意维度),它们均匀分布在所有方向上。为此,我为每个矢量分量生成正态分布的数字,并将结果按幅度的倒数进行缩放。
我的问题:我可以使用单个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;
}
谢谢。
答案 0 :(得分:1)
我假设您没有并行生成随机数。然后理论上,用一个引擎生成随机独立高斯向量没有问题。
每次调用std::normal_distribution
的{{1}}运算符都会在指定的高斯分布后为您提供随机实数值。 ()
运算符的连续调用会为您提供独立样本。 ()
(我的版本:gcc
)中的实现使用Marsaglia Polar方法生成标准正态随机数。您可以阅读this维基百科页面了解更多详情。
然而,对于需要高质量随机性和大量随机样本的严格科学研究,我建议使用Mersenne-Twister engine(4.8
32位或64位)而不是默认值引擎,因为它基于一种成熟的方法,具有很长的周期,并且在统计随机测试中表现良好。
答案 1 :(得分:1)
OP问:
我的问题:我可以使用单个std :: default_random_engine为我的矢量的所有组件生成数字,还是每个组件都需要自己的引擎?
我建议其他人在评论中说明没有使用std::default_random_engine
而是使用std::random_device
或std::chrono::high_resolution_clock
对random_device
或normal distribution
使用Gaussian
非常简单:
#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
显示here here有一个引擎,单个种子和单个分布,它生成随机数或随机数组单引擎的数字。
编辑 - 此外,您可以使用我作为random engines
和random distributions
的包装类编写的课程。你可以参考我的这个答案Error on Heroku。