您可以使用称为拒绝抽样的方法。这个想法是你有一些参数的函数(在你的例子中是 2 个参数 x
,y
),它代表概率密度函数。在您的 2D 案例中,您可以生成一个 x
,y
对以及一个表示概率 p
的变量。如果坐标处的概率密度函数较大(即 f(x,y) > p
),则添加样本,否则生成新对。你可以这样实现:
#include <functional>
#include <vector>
#include <utility>
#include <random>
std::vector<std::pair<double,double>> getDist(int num){
std::random_device rd{};
std::mt19937 gen{rd()};
auto pdf = [] (double x,double y) {
return /* Some probability density function */;
};
std::vector<std::pair<double,double>> ret;
double x,y,p;
while(ret.size() <= num){
x = (double)gen()/SOME_CONST_FOR_X;
y = (double)gen()/SOME_CONST_FOR_Y;
p = (double)gen()/SOME_CONST_FOR_P;
if(pdf(x,y) > p) ret.push_back({x,y});
}
return ret;
}
这是一个非常粗略的草案,但应该给出它如何运作的想法。
另一个选项(如果您想要正态分布)是 std::normal_distribution
。参考页面中的示例可以修改为:
#include <random>
#include <vector>
#include <utility>
std::vector<std::pair<double,double>> getDist(int num){
std::random_device rd{};
std::mt19937 gen{rd()};
std::normal_distribution<> d_x{x_center,x_std};
std::normal_distribution<> d_y{y_center,y_std};
while(ret.size() <= num){
ret.push_back({d_x(gen),d_y(gen)});
}
}
,
有多种方法可以解决此问题,具体取决于您想要的确切分布。一般而言,如果您有一个分布函数 f(x),它可以为您提供到中心特定距离处的点的概率,那么您可以对其进行积分以获得 cumulative distribution function F(x)。如果 CDF 可以反转,则可以使用 inverse CDF 将均匀随机变量映射到距中心的距离,从而获得所需的分布。但并非所有功能都可以轻松反转。
另一种选择是稍微伪造一下:例如,制作一个循环,从 0 到距中心的最大距离,然后对于每个距离,您使用概率函数来获得预期的点数那个距离。然后只需以随机选择的角度添加那么多点。这非常快,结果可能已经足够好了。
Lala5th 提到的拒绝采样是另一种选择,它为您提供所需的分布,但如果屏幕的大面积区域的概率非常低,则可能需要很长时间。确保它在有限时间内完成的一种方法是在添加 num
点之前不循环,而是循环遍历每个像素,并在 pdf(x,y) > p
时添加该像素的坐标。这样做的缺点是您不会得到准确的 num
分。
本文链接:https://www.f2er.com/4328.html