c语言等概率随机数,关于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 =>数字5

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

编辑:或者可能使用正确的数字创建一个数组,然后使用rand()更好的解决方案?

SO上有很多类似的问题......

cplusplus.com/reference/random/discrete_distribution/

相关的stackoverflow.com/questions/9432226/

你似乎走在正确的轨道上,但C ++已经有了一个专门的随机数分布,std::discrete_distribution

#include

#include

#include

#include

int main()

{

std::random_device rd;

std::mt19937 gen(rd());

// list of probabilities

std::vector 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 m;

for(int n=0; n<10000; ++n) {

++m[d(gen)];

}

for(auto p : m) {

std::cout << p.first <

";

}

}

在线演示:http://ideone.com/jU1ll

其他答案假设预期的分布与三角数的序列一起,但问题也指1-100和1-1000的范围,两者都不是三角形。 所以一般的答案似乎更合适。

@ shawnt00其他答案没有对输出范围做出这样的假设; 输出$ 1 $到$ 100范围内的数字,$他们将使用$ 100 $三角形数字。 但是,对于可以多次使用的固定分布,像这样的答案的方法可能仍然是一个不错的选择。

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

因此,插入1到15之间s的整数:

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

因此,您可以在恒定空间和恒定时间内从均匀分布到分布(没有迭代,也没有预先计算的表):

double my_distribution_from_uniform_distribution(double s) {

return ceil((sqrt(8*s + 1) - 1) / 2);

}

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

IEEE 754双精度数可以表示从1到2 ^ 53的所有整数(以及许多更大的整数,但在2 ^ 53之后不连续)。所以这个函数应该适用于从1到floor((2^53 - 1) / 8) = 1125899906842623的所有s。

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

S(n) = 1 + 2 + 3 + ... + (n - 1) + n

或简化:

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

这样可以避免存储阵列。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值