我有N个数n_1,n_2,... n_N和相关概率p_1,p_2,...,p_N。
函数应以概率p_i返回数字n_i,其中i = 1,...,N。
如何在c ++中建模?
我知道这不是一个难题。但我是c ++的新手,想知道你将使用什么功能。
你会产生0到1之间的统一随机数,如下所示:
((double) rand() / (RAND_MAX+1))
答案 0 :(得分:3)
这与我为这个问题给出的答案非常相似:
changing probability of getting a random number
你可以这样做:
double val = (double)rand() / RAND_MAX;
int random;
if (val < p_1)
random = n_1;
else if (val < p_1 + p_2)
random = n_2;
else if (val < p_1 + p_2 + p_3)
random = n_3;
else
random = n_4;
当然,这种方法只有p_1 + p_2 + p_3 + p_4 == 1.0
。
这很容易推广到具有几个数组和简单循环的可变数量的输出和概率。</ p>
答案 1 :(得分:1)
如果你知道编译时的概率,你可以使用我决定创建的这个可变参数模板版本。虽然实际上我并不建议使用它,因为源头是多么令人难以理解:P。
NumChooser <
Entry<2, 10>, // Value of 2 and relative probability of 10
Entry<5, 50>,
Entry<6, 80>,
Entry<20, 01>
> chooser;
chooser.choose(); // Returns the number 2 on average 10/141 times, etc.
Ideone 通常,基于模板的实现与基本实现非常相似。但是,存在一些差异:
-O2
优化或不进行优化,模板版本可以慢〜1-5%-O3
优化,模板版本在连续生成1到10,000次数字时实际上快了约1%。这使用rand()
来选择数字。如果统计上准确对您很重要,或者您想使用C ++ 11 <random>
,则可以使用第一个来源下方略微修改的版本。
#define onlyAtEnd(a) typename std::enable_if<sizeof...(a) == 0 > ::type
template<int a, int b>
class Entry
{
public:
static constexpr int VAL = a;
static constexpr int PROB = b;
};
template<typename... EntryTypes>
class NumChooser
{
private:
const int SUM;
static constexpr int NUM_VALS = sizeof...(EntryTypes);
public:
static constexpr int size()
{
return NUM_VALS;
}
template<typename T, typename... args>
constexpr int calcSum()
{
return T::PROB + calcSum < args...>();
}
template <typename... Ts, typename = onlyAtEnd(Ts) >
constexpr int calcSum()
{
return 0;
}
NumChooser() : SUM(calcSum < EntryTypes... >()) { }
template<typename T, typename... args>
constexpr int find(int left, int previous = 0)
{
return left < 0 ? previous : find < args... >(left - T::PROB, T::VAL);
}
template <typename... Ts, typename = onlyAtEnd(Ts) >
constexpr int find(int left, int previous)
{
return previous;
}
constexpr int choose()
{
return find < EntryTypes... >(rand() % SUM);
}
};
<random>
版#include <random>
#define onlyAtEnd(a) typename std::enable_if<sizeof...(a) == 0 > ::type
template<int a, int b>
class Entry
{
public:
static constexpr int VAL = a;
static constexpr int PROB = b;
};
template<typename... EntryTypes>
class NumChooser
{
private:
const int SUM;
static constexpr int NUM_VALS = sizeof...(EntryTypes);
std::mt19937 gen;
std::uniform_int_distribution<> dist;
public:
static constexpr int size()
{
return NUM_VALS;
}
template<typename T, typename... args>
constexpr int calcSum()
{
return T::PROB + calcSum < args...>();
}
template <typename... Ts, typename = onlyAtEnd(Ts) >
constexpr int calcSum()
{
return 0;
}
NumChooser() : SUM(calcSum < EntryTypes... >()), gen(std::random_device{}()), dist(1, SUM) { }
template<typename T, typename... args>
constexpr int find(int left, int previous = 0)
{
return left < 0 ? previous : find < args... >(left - T::PROB, T::VAL);
}
template <typename... Ts, typename = onlyAtEnd(Ts) >
constexpr int find(int left, int previous)
{
return previous;
}
int choose()
{
return find < EntryTypes... >(dist(gen));
}
};
// Same usage as example above
答案 2 :(得分:0)
也许像(未经测试的代码!)
/* n is the size of tables, numtab[i] the number of index i,
probtab[i] its probability; the sum of all probtab should be 1.0 */
int random_inside(int n, int numtab[], double probtab[])
{
double r = drand48();
double p = 0.0;
for (int i=0; i<n; i++) {
p += probtab[i];
if (r>=p) return numtab[i];
}
}
答案 3 :(得分:0)
在上一条评论中,您有正确答案:
how-to-select-a-value-from-a-list-with-non-uniform-probabilities