C语言 仅使用 rand() 的任意概率分布的随机数



我正在寻找一种简单的算法,如何仅使用 ANSI rand() 函数但具有任意概率分布来生成伪随机浮点数。对于简单的均匀分布,我使用以下代码:

x = (float)rand() / (float)RAND_MAX;

当然不是很准确,但足以满足我的需求。我还需要其他分布,如逻辑和高斯分布。理想情况下,我必须使用有限长度的简单向量定义任意pdf,例如,对于逻辑pdf,此向量可能如下所示:

logistic_pdf = {0., 0.26894, 0.33924, 0.41742, 0.5, 0.58257, 0.66075, 1.};

对于均匀(使用相同的维度 8):

uniform_pdf = {0.125, 0.125, 0.125, 0.125, 0.125, 0.125, 0.125, 0.125};

这只是一个想法。但我不确定如何仅使用 rand()->{0...RAND_MAX} 有效地实现它。

没有简单的算法可以做任意复杂的事情。 你必须找到每个"Arbirary"分布的逆概率积分变换。

对于

任意离散分布,有一个线性时间初始化常量时间采样算法:

http://web.eecs.utk.edu/~vose/Publications/random.pdf

看看吧!这是非常聪明的,一点也不难实现。

你的问题没有一个简单的答案。 Luc Devroye花了800多页在他的文本"非均匀随机变量生成"中非常全面地解决了这个问题。

看看这个链接。下面是泊松分布的示例:

#include < stdlib.h > 
#include < math.h >
int Poisson ( double ev ) {
      int         n = 0;      // counter of iterations 
      double      em;         // e^(-ev), where v is the expected value
      double      x;          // pseudorandom number
      em = exp (-ev);
      x = rand() / (double) RAND_MAX;     // check your C compiler docs
                                          // for the correct constant name
      while (x > em) { 
            n++;
            x *=  rand() / (double) RAND_MAX;
            }
      return n;
      } 
main () {
  int i;
  for (i = 0; i< 1000; i++) {
    printf("new Poisson value: %dn", Poisson(.133333) );
    }
  }

你将不得不做一些研究,因为从每个分布中绘制伪随机值的方法会有所不同。 一个合理的起点是维基百科。 它们具有从正态/高斯分布和逻辑分布生成值的方法。 其他可能感兴趣的是指数分布,β 分布和伽马分布。

或者,如果您有一些想要复制的源数据,则可以创建您拥有的数据的直方图,并从该数据生成 CDF。 然后只需生成 X~U(0,1),并确定这对应于直方图中的哪个箱,在箱的上限和下限之间线性缩放。 这就是斯塔凡提到的逆概率积分变换方法的本质。

最新更新