C++ 基于概率的随机数
我很难生成不遵循离散均匀分布的随机数 例如,假设我有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数。。。有什么更好的方法可以做到这一点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。这是我想要的方式吗?我已经构建了一个循环,每次需要生成一个数字时,它几乎都会这样做,我认为这可能是低效的,因为它会一
编辑:或者用适当的数字创建一个数组,然后用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);
}