在C ++中实现正常分布的制服比例

时间:2012-10-21 19:41:22

标签: c++ random normal-distribution

我知道这可以通过定义泪珠形状并接受落在该区域内的点(来自均匀的发生器)来完成。

我试图在C ++中通过生成两个均匀的随机数x和y来定位点(x,y),然后检查这个点是否属于该区域。

我对代码本身没有问题,但我的逻辑中存在缺陷吗?我还没有找到合适的图形方式来检查这是否是真正的正态分布。

这是应该起作用的代码:

typedef unsigned long long int Ullong;
typedef double Doub;

struct Normaldev : Ran {
    Doub mu,sig;

    Normaldev (Doub mmu, Doub ssig, Ullong i)
        : Ran (i), mu(mmu), sig(ssig){}

    Doub dev() {

      Doub u, v, x, y, q;
        do {
          u=Doub();
          v=1.7156*(Doub()-0.5);
          x=u-0.449871;
          y=abs(v)+0.386595;
          q=x*x+y*(0.19600*y-0.25472*x);
        } while(q>0.27597 && (q>0.27846 || v*v>-4*log(u)*u*u));

        return mu+sig*v/u;
     }
};

我尽可能多地根据我对C ++的基本知识更改了“数字食谱”一书中的建议代码,但是Ran究竟应该是什么?

2 个答案:

答案 0 :(得分:1)

  

我尽可能多地根据我对C ++的基本知识更改了“数字食谱”一书中的建议代码,但是Ran究竟应该是什么?

Ran是NormalDev的父类。它没有在你给出的代码中定义。根据代码,它似乎是一个非常通用的随机数类,在其构造函数中采用unsigned long long int种子。

答案 1 :(得分:-1)

查看第3版“C中的数字食谱”,第364-369页。你会发现Box-Muller返回两个正态分布的随机变量,即'u'和'v'。因此,第一次调用该函数时,您计算两个变量,但只返回'u'。函数的第二次调用只会返回'v'。

double  u, v;
double  sigma = 1.0
double  mean  = 0.0;
int     flag  = 0;

double boxMuller()
{
    if (flag == 1) {
        flag  = 0;
        return v * sigma + mean;
    }
    double help;
    do {
        u = Doub() - 0.5;
        v = Doub() - 0.5;
        help      = u * u + v * v;
    } while (help >= 0.25);
    help = sqrt( log( help * 4.0 ) / help * -2.0 );
    u   *= help;
    v   *= help;
    flag = 1;
    return u * sigma + mean;
}

相比之下,制服比率方法必须在每次通话时计算一个新的随机变量(不是每一秒)。

所以我测量了时间,并且更喜欢使用上面的Box-Muller代码。