C++ 基于概率的随机数

C++ 基于概率的随机数,c++,random,distribution,probability,C++,Random,Distribution,Probability,我很难生成不遵循离散均匀分布的随机数 例如,假设我有5个数字(为了简单起见),生成数字k的概率是k/15。(k=1到5) 我的想法是使用rand()生成一个随机数j,如果这个数j是: 1=>然后生成数字1 2或3=>num 2 4或5或6=>num 3 7或8或9或10=>num 4 11或12或13或14或15=>num 5 现在将其缩放到生成1-10、1-100、1-1000。这是我想要的方式吗?我已经构建了一个循环,每次需要生成一个数字时,它几乎都会这样做,我认为这可能是低效的,因为它会一

我很难生成不遵循离散均匀分布的随机数

例如,假设我有5个数字(为了简单起见),生成数字k的概率是k/15。(k=1到5)

我的想法是使用rand()生成一个随机数j,如果这个数j是:

1=>然后生成数字1

2或3=>num 2

4或5或6=>num 3

7或8或9或10=>num 4

11或12或13或14或15=>num 5

现在将其缩放到生成1-10、1-100、1-1000。这是我想要的方式吗?我已经构建了一个循环,每次需要生成一个数字时,它几乎都会这样做,我认为这可能是低效的,因为它会一直上升,直到找到在其中一个范围内生成的j数。。。有什么更好的方法可以做到这一点


编辑:或者用适当的数字创建一个数组,然后用rand()更好的解决方案退出?

你可以利用这个奇怪的算术事实:

S(n) = 1 + 2 + 3 + ... + (n - 1) + n
或简化:

S(n) = n * (n + 1) / 2

这可以避免存储数组。

你似乎在正确的轨道上,但是C++已经有了专门的随机数分布,<代码> STD::DeXTILIONDIAGION/COMPUTIO/

#include <iostream>
#include <vector>
#include <map>
#include <random>

int main()
{
    std::random_device rd;
    std::mt19937 gen(rd());

    // list of probabilities    
    std::vector<double> p = {0, 1.0/15, 2.0/15, 3.0/15, 4.0/15, 5.0/15};
    // could also be min, max, and a generating function (n/15 in your case?)
    std::discrete_distribution<> d(p.begin(), p.end());

    // some statistics
    std::map<int, int> m;
    for(int n=0; n<10000; ++n) {
        ++m[d(gen)];
    }
    for(auto p : m) {
        std::cout << p.first << " generated " << p.second << " times\n";
    }
}
#包括
#包括
#包括
#包括
int main()
{
std::随机_装置rd;
标准:mt19937 gen(rd());
//概率表
向量p={0,1.0/15,2.0/15,3.0/15,4.0/15,5.0/15};
//也可以是最小值、最大值和生成函数(在您的情况下为n/15?)
离散分布d(p.begin(),p.end());
//一些统计数字
std::map m;

对于(int n=0;n考虑从1到
n
的整数的和
s
s=n*(n+1)/2
。求解
n
得到
n=(±sqrt(8*s+1)-1)/2
。我们可以忽略负平方根,因为我们知道
n
是正的。因此
n=(sqrt(8*s+1)-1)/2

因此,为
s
插入介于1和15之间的整数:

s  n
01 1.000000
02 1.561553
03 2.000000
04 2.372281
05 2.701562
06 3.000000
07 3.274917
08 3.531129
09 3.772002
10 4.000000
11 4.216991
12 4.424429
13 4.623475
14 4.815073
15 5.000000
如果我们取每个计算的
n
(最小整数不小于
n
)的上限,我们得到:

s  n
01 1
02 2
03 2
04 3
05 3
06 3
07 4
08 4
09 4
10 4
11 5
12 5
13 5
14 5
15 5
因此,您可以从均匀分布转到恒定空间和恒定时间(无迭代和预计算表)中的分布:

注意:这取决于
sqrt
给出完美平方的精确结果(例如,精确返回7,精确返回49)。这通常是一个安全的假设,因为IEEE 754要求平方根的精确舍入


IEEE 754 Double可以表示从1到2^53的所有整数(以及许多更大的整数,但不能在2^53之后连续)。因此,此函数应能正确地用于从1到楼层((2^53-1)/8)的所有
s
=1125899906842623

有许多类似的问题,因此…..其他答案假设预期分布与三角形数字的顺序一致,但问题也涉及1-100和1-1000的范围,两者都不是三角形。因此一般答案似乎更合适。@shawnt00其他答案对输出范围没有这样的假设;要输出1美元到100美元范围内的数字,他们将使用第100美元的三角形数字。然而,对于一个会被多次使用的固定分布,像这样的答案可能仍然是一个好的选择。
double my_distribution_from_uniform_distribution(double s) {
    return ceil((sqrt(8*s + 1) - 1) / 2);
}