C++ 如何生成指数分布的随机数(平均值)?

C++ 如何生成指数分布的随机数(平均值)?,c++,exponential-distribution,C++,Exponential Distribution,我试图生成平均值等于1的指数分布随机数。我知道如何得到具有均值和标准差的正态分布的随机数。我们可以通过正态(平均值,标准偏差)得到它,但我不知道如何得到指数分布的随机数 有人能帮我吗?生成指数分布随机变量可以通过以下方式完成: -ln(U)/lambda (where U~Uniform(0,1)). 更多信息可在中找到 在指数分布中:lamda=1/mean,因此它可以得到: myVar = -ln(U) * mean (where U~Uniform(0,1)). 对于C++11,该

我试图生成平均值等于1的指数分布随机数。我知道如何得到具有均值和标准差的正态分布的随机数。我们可以通过
正态(平均值,标准偏差)
得到它,但我不知道如何得到指数分布的随机数


有人能帮我吗?

生成指数分布随机变量可以通过以下方式完成:

-ln(U)/lambda (where U~Uniform(0,1)). 
更多信息可在中找到

在指数分布中:
lamda=1/mean
,因此它可以得到:

myVar = -ln(U) * mean (where U~Uniform(0,1)). 
对于C++11,该标准实际上保证了在STL中有一个符合指数分布要求的RNG,并且适合对象类型有一个非常描述性的名称

指数分布随机发生器中的平均值通过公式
E[X]=1/lambda
1计算

std::exponential_distribution
有一个以lambda为参数的构造函数,因此我们可以通过计算lambda的值并将其传递给生成器,轻松创建一个遵循规则的对象

std::exponential_distribution rng (1/1); // lambda = 1 / E[X]

脚注
1.根据


以可读ascii图表形式分发

I找到了基本示例。不过,我还没有检查它是否真的有效。如果你有统一随机数的来源,维基百科的页面包含一个方法:你希望U出现在
(0,1)
中,而不是在实践中出现
[0,1]
,因为真正的RNG是离散的,而不是连续的。您不想从均匀RNG得到结果
1
(因此在“指数分布”中产生0),您也不想从均匀RNG得到结果
0
。@SteveJessop:谢谢您的更正,因为我们不是在处理真实的连续分布,但是仅仅用离散值模拟一个,你是绝对正确的。@Steve:不同意
+0
+infinity
是指数分布样本的浮点近似值的完美合理输出。如何处理溢出和下溢(以及其他极端示例)来自实际分析应用程序的需求,而不是对简并和其他边缘条件的哲学厌恶。@Hurkyl:
log(0)
不返回
-无穷大
,它返回
-巨大的值
,这意味着此函数将返回
+magive_VAL*mean
。当
mean
为1时,我想调用者可以处理这个问题,但在我看来,当
mean<1
时,调用者处理的边缘情况并不是那么好。这就是说,如果
U
[0,1]
上确实是一个统一的双精度,那么它只发生在2^53中的1,所以大多数呼叫者不需要处理它。不管它是否包含在内,都不会使分布有太大的偏差。@user4786271不,这是一个算法解释,说明了如何做。应该很容易用任何语言实现。你能解释一下这一行吗:
std::mt19937 rnd_gen(rd())和这个:
rng(rnd\u gen)
?一旦你有了指数分布,你为什么需要这个
mt19937
东西?@bobroxsox
rnd\u gen
是用来输出稳定数字流的生成器,
rng
是负责通过
rnd\u gen
来调整数字产量的分布对象。啊,这是有道理的。谢谢
#include <iomanip>
#include <random>
#include <map>
#include <iostream>

int
main (int argc, char *argv[])
{
  double const exp_dist_mean   = 1;
  double const exp_dist_lambda = 1 / exp_dist_mean;

  std::random_device rd; 

  std::exponential_distribution<> rng (exp_dist_lambda);
  std::mt19937 rnd_gen (rd ());

  /* ... */

  std::map<int, int> result_set;

  for (int i =0; i < 100000; ++i)
    ++result_set[rng (rnd_gen) * 4]; 

  for (auto& v : result_set) {
    std::cout << std::setprecision (2) << std::fixed;

    std::cout << v.first/4.f << " - " << (v.first+1)/4.f << " -> ";
    std::cout << std::string (v.second/400, '.') << std::endl;

    if (v.second/400 == 0)
      break;
  }
}
0.00 - 0.25 -> ........................................................
0.25 - 0.50 -> ...........................................
0.50 - 0.75 -> .................................
0.75 - 1.00 -> .........................
1.00 - 1.25 -> ....................
1.25 - 1.50 -> ...............
1.50 - 1.75 -> ............
1.75 - 2.00 -> .........
2.00 - 2.25 -> .......
2.25 - 2.50 -> .....
2.50 - 2.75 -> ....
2.75 - 3.00 -> ...
3.00 - 3.25 -> ..
3.25 - 3.50 -> ..
3.50 - 3.75 -> .
3.75 - 4.00 -> .
4.00 - 4.25 -> .
4.25 - 4.50 ->