[C++] 关于不同分布的随机数的生成

源于SJ加分题的发红包,想到如何生成制定分布的随机数。

当时就想到红包的值应该是以红包的平均值为峰值的正态的分布。(后来想想应该是偏态分布)这个分布的平均值是红包的平均值。实际上,那个函数的具体实现方法应该是也不是这么简单,我还没找到合适的方法。

前几天看机器学习的时候看到一个Gamma分布(看这个图形的样子的好像是偏态分布。就去学习了一番。

平均分布

过于简单,不再赘述

正态分布

最广为流传的方式应该就是Box-Muller的变换了。U_1, U_2是随机分布的[0~1]内的随机数

    \[U_1=Rand()\quad U_2=Rand()\]

    \[Z=R*\cos(\theta)\]

    \[R=\sqrt{-2*\ln(U_2)}\]

    \[\theta=2*\pi*U_1\]

这样的Z就是符合正态分布的随机数了。

Gamma分布

发现网上也没什么资料,不过C++11提供了很多现成的库来生成不同分布的随机数。这是C++PLUSPLUS的URL

有Gamma分布,Binomial分布,还有指数分布,大概有十多个。

// gamma_distribution
#include <iostream>
#include <random>

int main()
{
  const int nrolls=10000;  // number of experiments
  const int nstars=100;    // maximum number of stars to distribute

  std::default_random_engine generator;
  std::gamma_distribution<double> distribution(2.0,2.0);

  int p[10]={};

  for (int i=0; i<nrolls; ++i) {
    double number = distribution(generator);
    if (number<10) ++p[int(number)];
  }

  std::cout << "gamma_distribution (2.0,2.0):" << std::endl;

  for (int i=0; i<10; ++i) {
    std::cout << i << "-" << (i+1) << ": ";
    std::cout << std::string(p[i]*nstars/nrolls,'*') << std::endl;
  }

  return 0;
}

Possible output:

gamma_distribution (2.0,2.0):
0-1: *********
1-2: *****************
2-3: ******************
3-4: **************
4-5: ************
5-6: *********
6-7: *****
7-8: ****
8-9: ***
9-10: **

UPDATE(2019/7/31):
在知乎上看到的TESTU01,可以用来检验随机数生成的随机性(Random Number Generator, RNG),有官方文档用来证明验证的方式和验证函数的使用。

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注