由于您在分发方面很灵活,因此无需执行拒绝逻辑即可提供合理结果的简单解决方案是triangular distribution。 IE。您将三角形的下端设置为 1,000,将三角形的上端设置为 20,000,三角形的尖端设置为您想要的平均值 9,000。
上面的维基百科链接表明三角形分布的平均值是:
(a + b + c) / 3
其中a 和b 分别是您的下限和上限,c 是三角形的尖端。对于您的输入,简单代数表明 c = 6,000 将给出您想要的平均值 9,000。
C++ 的<random> 标头中有一个名为std::piecewise_linear_distribution 的分布,非常适合设置三角分布。这只需要两条直线。构建这种三角分布的一种简单方法是:
std::piecewise_linear_distribution<> dist({1000., 6000., 20000.},
[](double x)
{
return x == 6000 ? 1. : 0.;
});
现在您只需将 URNG 插入此发行版并生成结果。为了理智起见,根据您的问题陈述收集一些重要的统计数据也很有帮助,例如最小值、最大值和平均值。
这是一个完整的程序:
#include <algorithm>
#include <iostream>
#include <numeric>
#include <random>
#include <vector>
int
main()
{
std::mt19937_64 eng;
std::piecewise_linear_distribution<> dist({1000., 6000., 20000.},
[](double x)
{
return x == 6000 ? 1. : 0.;
});
std::vector<double> results;
for (int i = 0; i < 100; ++i)
results.push_back(dist(eng));
auto avg = std::accumulate(results.begin(), results.end(), 0.) / results.size();
auto minmax = std::minmax_element(results.begin(), results.end());
std::cout << "size = " << results.size() << '\n';
std::cout << "min = " << *minmax.first << '\n';
std::cout << "avg = " << avg << '\n';
std::cout << "max = " << *minmax.second << '\n';
}
这个应该可移植地输出:
size = 100
min = 2353.05
avg = 8972.1
max = 18162.5
如果您将采样值的数量提高到足够高,您将看到参数收敛:
size = 10000000
min = 1003.08
avg = 8998.91
max = 19995.5
根据需要播种。