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

C 仅使用rand()的具有任意概率分布的随机数,c,algorithm,math,random,probability,C,Algorithm,Math,Random,Probability,我正在寻找一个简单的算法,如何仅使用ANSI rand()函数生成具有任意概率分布的伪随机浮点数。对于简单的均匀分布,我使用以下代码: x = (float)rand() / (float)RAND_MAX; 当然它不是很准确,但足以满足我的需要。我还需要其他分布,如逻辑和高斯分布。理想情况下,我必须使用有限长度的简单向量定义任意pdf,例如,对于逻辑pdf,该向量可能如下所示: logistic_pdf = {0., 0.26894, 0.33924, 0.41742, 0.5, 0.582

我正在寻找一个简单的算法,如何仅使用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):

这只是一个想法。但是我不知道如何仅使用
rand()->{0…rand_MAX}
有效地实现它。

看看这个。这里是泊松分布的一个示例:

#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: %d\n", Poisson(.133333) );
    }
  }
#包括
#包括
整数泊松(双ev){
int n=0;//迭代计数器
double em;//e^(-ev),其中v是期望值
双x;//伪随机数
em=exp(-ev);
x=rand()/(double)rand_MAX;//检查您的C编译器文档
//获取正确的常量名称
而(x>em){
n++;
x*=兰特()/(双)兰特最大值;
}
返回n;
} 
主要(){
int i;
对于(i=0;i<1000;i++){
printf(“新泊松值:%d\n”,泊松(.133333));
}
}

您必须做一些研究,因为从每个分布中提取psuedo随机值的方法会有所不同。一个合理的起点是维基百科。它们有从和生成值的方法。其他可能感兴趣的是, 这个,这个


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

没有简单的算法来处理任意复杂的事情。您必须找到每个“任意”分布的采样点。

对于任意离散分布,有一种线性时间初始化恒定时间采样算法:


看看!它非常聪明,而且一点也不难实现。

您的问题没有简单的答案。Luc Devroye用了800多页的篇幅在他的文本中非常全面地阐述了这一点。

我同意你回答的精神,但应该指出,逆变换并不是唯一可用的方法。事实上,它不适用于累积分布函数,这些函数不像高斯函数那样是可逆的(因为积分没有很好的闭合形式)。我建议你参考一篇关于这个主题的文章,比如谢尔顿·罗斯的模拟,因为这个主题可能比他想象的要多。我想这可能比你想象的要多。我建议您参考Sheldon Ross的Simulation,因为它很好地涵盖了如何为离散和连续情况下的不同分布生成随机数。
#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: %d\n", Poisson(.133333) );
    }
  }