我需要一个类似于 betarand(a,b)
的 C 或 C++ 源代码的函数,该函数生成符合贝塔分布的随机数。我知道可以使用 boost 库,但我要将其移植到 CUDA 架构中,所以需要该源代码。有人能帮我吗?
同时,我有 betapdf
(贝塔概率密度函数)。但我不知道如何使用它来创建随机数 :)
我需要一个类似于 betarand(a,b)
的 C 或 C++ 源代码的函数,该函数生成符合贝塔分布的随机数。我知道可以使用 boost 库,但我要将其移植到 CUDA 架构中,所以需要该源代码。有人能帮我吗?
同时,我有 betapdf
(贝塔概率密度函数)。但我不知道如何使用它来创建随机数 :)
C++11的随机数库没有提供beta分布。不过,可以用两个gamma分布来模拟beta分布,而这个库确实提供了gamma分布。我已经为您使用std::gamma_distribution
实现了一个beta_distribution
。据我所知,它完全符合随机数分布的要求。
#include <iostream>
#include <sstream>
#include <string>
#include <random>
namespace sftrabbit {
template <typename RealType = double>
class beta_distribution
{
public:
typedef RealType result_type;
class param_type
{
public:
typedef beta_distribution distribution_type;
explicit param_type(RealType a = 2.0, RealType b = 2.0)
: a_param(a), b_param(b) { }
RealType a() const { return a_param; }
RealType b() const { return b_param; }
bool operator==(const param_type& other) const
{
return (a_param == other.a_param &&
b_param == other.b_param);
}
bool operator!=(const param_type& other) const
{
return !(*this == other);
}
private:
RealType a_param, b_param;
};
explicit beta_distribution(RealType a = 2.0, RealType b = 2.0)
: a_gamma(a), b_gamma(b) { }
explicit beta_distribution(const param_type& param)
: a_gamma(param.a()), b_gamma(param.b()) { }
void reset() { }
param_type param() const
{
return param_type(a(), b());
}
void param(const param_type& param)
{
a_gamma = gamma_dist_type(param.a());
b_gamma = gamma_dist_type(param.b());
}
template <typename URNG>
result_type operator()(URNG& engine)
{
return generate(engine, a_gamma, b_gamma);
}
template <typename URNG>
result_type operator()(URNG& engine, const param_type& param)
{
gamma_dist_type a_param_gamma(param.a()),
b_param_gamma(param.b());
return generate(engine, a_param_gamma, b_param_gamma);
}
result_type min() const { return 0.0; }
result_type max() const { return 1.0; }
result_type a() const { return a_gamma.alpha(); }
result_type b() const { return b_gamma.alpha(); }
bool operator==(const beta_distribution<result_type>& other) const
{
return (param() == other.param() &&
a_gamma == other.a_gamma &&
b_gamma == other.b_gamma);
}
bool operator!=(const beta_distribution<result_type>& other) const
{
return !(*this == other);
}
private:
typedef std::gamma_distribution<result_type> gamma_dist_type;
gamma_dist_type a_gamma, b_gamma;
template <typename URNG>
result_type generate(URNG& engine,
gamma_dist_type& x_gamma,
gamma_dist_type& y_gamma)
{
result_type x = x_gamma(engine);
return x / (x + y_gamma(engine));
}
};
template <typename CharT, typename RealType>
std::basic_ostream<CharT>& operator<<(std::basic_ostream<CharT>& os,
const beta_distribution<RealType>& beta)
{
os << "~Beta(" << beta.a() << "," << beta.b() << ")";
return os;
}
template <typename CharT, typename RealType>
std::basic_istream<CharT>& operator>>(std::basic_istream<CharT>& is,
beta_distribution<RealType>& beta)
{
std::string str;
RealType a, b;
if (std::getline(is, str, '(') && str == "~Beta" &&
is >> a && is.get() == ',' && is >> b && is.get() == ')') {
beta = beta_distribution<RealType>(a, b);
} else {
is.setstate(std::ios::failbit);
}
return is;
}
}
像这样使用:
std::random_device rd;
std::mt19937 gen(rd());
sftrabbit::beta_distribution<> beta(2, 2);
for (int i = 0; i < 10000; i++) {
std::cout << beta(gen) << std::endl;
}
x_gamma(engine) / (x_gamma(engine) + y_gamma(engine)
,即在分子和分母中使用两个不同的x
样本,很容易产生非常大的值(>>1),因为分母中的x+y
可能比分子中的另一个x
样本小得多。这不符合beta分布被限制在1以内的属性。当在分子和分母中使用相同的x
样本时,得到的值不会超过1。因此,@Joseph Mansfield的原始代码更有可能是正确的! - lnstadrum#include <random>
#include <boost/math/special_functions/beta.hpp>
template<typename URNG>
double beta_sample(URNG& engine, double a, double b)
{
static std::uniform_real_distribution<double> unif(0,1);
double p = unif(engine);
return boost::math::ibeta_inv(a, b, p);
// Use Boost policies if it's not fast enough
}