无偏随机数发生器

nag*_*dra 3 c++ random

我使用以下代码在域中生成随机数.当我绘制它们时,它们看起来分组在右边.我可以告诉你我的情节,但我不知道如何上传它.基本上我将一些数据值与相应的点相关联.你能告诉我怎样才能纠正它?我的完整代码是

#include <iostream>
#include <cmath>
#include <fstream>
#include <sstream>
#include <string>
#include <cstdlib>
#include <cstdio>
#include <time.h>

using namespace std;
string int2string1( int l );
string int2string2( int m );
int main ()
{
    ofstream outFile;
    ofstream myimp;
    string filename;
    srand((unsigned)time(0));
    int nx = 400;
    int ny = 200;
    int i,j,ix,iy,xm,ym,nimp,nfam[nx][ny];
    float vo,rnd,rr,rad,sig,vimp[nx][ny];
    for (i=0; i<nx; i++)
    {
        for (j=0; j<ny; j++)
        {
            vimp[i][j] = 0.0;
        }
    }
    rad = 5.0;
    xm = 0;
    ym = 0;
    vo = 0.08;
    sig = 4.0;
    myimp.open("imp.dat");
    for(i=1; i<nx-1; i++)
    {
        for(j=1; j<ny-1; j++)
        {
            rnd = (random() %1000 + 1)*1.0/1000.0;
            if(rnd>0.99)
            {
                xm = random() % 398 + 1;              /***1 through 399 ***/
                ym = random() % 198 + 1;              /***1 through 199 ***/
                for(ix=xm-5; ix<=xm+5; ix++)
                {
                    for(iy=ym-5; iy<=ym+5; iy++)
                    {
                        rr = sqrt(pow(ix-xm,2.)+pow(iy-ym,2.));
                        if(rr<=rad)
                        {
                            vimp[ix][iy] = vo*1.6e-19;
                        }
                    }
                }
            }
            myimp<<i<<"\t\t"<<j<<"\t\t"<<xm<<"\t\t"<<ym<<"\t\t"<<nfam[i][j]<<"\t\t"<<vimp[i][j]*6.23e18<<"\n";
        }
    }
    myimp.close();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

seh*_*ehe 11

int r = rand() % N;
Run Code Online (Sandbox Code Playgroud)

不会导致均匀分布1

相反,我建议只使用C++ TR1(或boost)随机:

#include <random>

std::mt19937 rng(seed);
std::uniform_int_distribution<int> gen(0, N); // uniform, unbiased

int r = gen(rng);
Run Code Online (Sandbox Code Playgroud)

或者生成任何类型的浮点数:

std::uniform_real_distribution<double> gen(-2*PI, +2*PI); // uniform, unbiased
double r = gen(rng);
Run Code Online (Sandbox Code Playgroud)

1背景,例如:使用rand()

如果你真的卡住使用兰特()和N不整除 MAX_RAND,页面有关于如何实现一些提示有些使用其他公式更好的整数分布.请注意,我会引导您转向AndréCaron的答案.

  • 但请注意,您在此处发布的所有包装器都会引入偏差,除非RAND_MAX是所请求范围的精确倍数(这种情况很少见 - 通常是不可能的).我们只能希望标准库中的那些做得更好. (2认同)

And*_*ron 7

基本上,如果rand() % N表达式RAND_MAX不是倍数,则表达式会引入偏差N.它以非均匀的方式[0,RAND_MAX]将数字投射到范围内[0,N].

假设RAND_MAX=4N=2.然后,有3个数字产生0(0,24),2个数字产生1(13).因此,你有60%的获得变化0和40%的获得机会1.

从实现的无偏投影正确的方法[0,RAND_MAX][0,N]是通过调用rand()多次,直到随机值是在所需的时间间隔.请参阅Java 文档Random.nextInt()(Oli Charlesworth的信用链接).

假设,对于纯粹的执行速度,您希望避免rand()多次调用,生成最小偏差的方法是使用中间double数,例如:

double myrand ()
{
    return double(rand()) / double(RAND_MAX);
}

int myrand ( int max )
{
    return int(myrand() * double(max));
}
Run Code Online (Sandbox Code Playgroud)

编辑: 这是一个简单的类,它将rand()函数的输出投影到一个[0,N]没有偏差的范围rand().

class BoundedRandom
{
    const int m_maximum;
    const int m_divisor;
public:
    BoundedRandom ( int maximum )
        : m_maximum(maximum),
          m_divisor(RAND_MAX/(maximum+1))
    {}

    int operator() ()
    {
        int result = rand() / m_divisor;
        while ( result > m_maximum ) {
            result = rand() / m_divisor;
        }
        return (result);
    }
};
Run Code Online (Sandbox Code Playgroud)

注意:未经测试或调试.

您可以像这样使用此生成器:

BoundedRandom randomx(398);
BoundedRandom randomy(198);
// ...
 xm = randomx() + 1; // 1 through 399
 ym = randomy() + 1; // 1 through 199
Run Code Online (Sandbox Code Playgroud)

  • @DavidHeffernan:当`RAND_MAX`和`N`较大时,偏差肯定是*较小*.这是否可以忽略不计*取决于`RAND_MAX`,`N`和应用程序的具体值. (3认同)
  • “假设 RAND_MAX=4 且 N=2。” 他们不是。当您插入真实值时,您所说的偏差可以忽略不计。 (2认同)