3

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

我试图在 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 到底应该是什么?

4

2 回答 2

1

我用我对 C++ 的基本知识尽可能多地更改了数字食谱书中建议的代码,但 Ran 到底应该是什么?

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

于 2012-10-22T13:32:11.593 回答
-2

请查看“C 中的数字食谱”的第 3 版,第 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;
}

相比之下,Ratio-of-Uniforms 方法必须在每次调用时(而不是每秒)计算一个新的随机变量。

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

于 2013-04-20T16:58:09.650 回答