Ну, вы можете вычислить вероятности из нормального распределения в заданных точках и использовать их для дискретной выборки.
Вдоль линий
#include <cmath>
#include <random>
#include <iostream>
constexpr double PI = 3.14159265359;
static inline double squared(const double x) {
return x * x;
}
double GaussPDF(const double x,
const double mu,
const double sigma) {
return exp(-0.5 * squared((x - mu) / sigma)) / (sqrt(2.0 * PI) * sigma);
}
int SampleTruncIntGauss(const int xmin, const int xmax, const double mu, const double sigma, std::mt19937_64& rng) {
int n = xmax - xmin + 1;
std::vector<double> p(n);
for (int k = 0; k != n; ++k)
p[k] = GaussPDF(static_cast<double>(xmin) + k, mu, sigma);
std::discrete_distribution<int> igauss{ p.begin(), p.end() };
return xmin + igauss(rng);
}
int main() {
int xmin = -3;
int xmax = 5;
int n = xmax - xmin + 1;
double mu = 1.2;
double sigma = 2.3;
std::mt19937_64 rng{ 98761728941ULL };
std::vector<int> h(n, 0);
for (int k = 0; k != 10000; ++k) {
int v = SampleTruncIntGauss(xmin, xmax, mu, sigma, rng);
h[v - xmin] += 1;
}
int i = xmin;
for (auto k : h) {
std::cout << i << " " << k << '\n';
++i;
}
return 0;
}
Вы можете сделать код более оптимальным, я переинициализируюмассив вероятностей каждый раз, когда мы проводим выборку, но он демонстрирует суть идеи.
ОБНОВЛЕНИЕ
Вы также можете использовать неточечные вероятности для выборки, в основном предполагая, что вероятность в целочисленной точке x
означает вероятность иметь значение в диапазоне [x-0.5 ... x + 0.5].Это можно легко выразить с помощью гауссовского CDF.
constexpr double INV_SQRT2 = 0.70710678118;
double GaussCDF(const double x,
const double mu,
const double sigma) {
double v = INV_SQRT2 * (x - mu) / sigma;
return 0.5 * (1.0 + erf(v));
}
double ProbCDF(const int x,
const double mu,
const double sigma) {
return GaussCDF(static_cast<double>(x) + 0.5, mu, sigma) - GaussCDF(static_cast<double>(x) - 0.5, mu, sigma);
}
и код вероятностей будет
for (int k = 0; k != n; ++k) {
p[k] = ProbCDF(xmin + k, mu, sigma);
Результат немного отличается, но все еще напоминает гауссовский