[英]unbiased random number generator
我使用以下代码在域中生成随机数。 当我绘制它们时,它们看起来分组在右边。 我可以告诉你我的情节,但我不知道如何上传它。 基本上我将一些数据值与相应的点相关联。 你能告诉我怎样才能纠正它? 我的完整代码是
#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;
}
int r = rand() % N;
不会导致均匀分布1
相反,我建议只使用C ++ TR1(或boost)随机:
#include <random>
std::mt19937 rng(seed);
std::uniform_int_distribution<int> gen(0, N); // uniform, unbiased
int r = gen(rng);
或者生成任何类型的浮点数:
std::uniform_real_distribution<double> gen(-2*PI, +2*PI); // uniform, unbiased
double r = gen(rng);
1 Backgound,例如: 使用rand()
如果你真的卡住使用兰特()和N不整除 MAX_RAND
,页面有关于如何实现使用其他公式有所好转整数分布一些提示。 请注意,我会引导您转向AndréCaron的答案 。
基本上,如果RAND_MAX
不是N
的倍数,则rand() % N
表达式会引入偏差。 它以[0,RAND_MAX]
将数字以非均匀方式投影到范围[0,N]
上。
假设RAND_MAX=4
且N=2
。 然后,存在产生3个数字0
( 0
, 2
和4
产生)和2号1
( 1
和3
)。 因此,你得到60%的变化0
和40%获得1
机会。
实现从[0,RAND_MAX]
到[0,N]
的无偏投影的正确方法是重复调用rand()
,直到随机值在所需的间隔内。 请参阅Java中的Random.nextInt()
文档Random.nextInt()
Oli Charlesworth的Credits链接)。
假设,对于纯粹的执行速度,您希望避免多次调用rand()
,生成最小偏差的方法是使用中间double
数,例如:
double myrand ()
{
return double(rand()) / double(RAND_MAX);
}
int myrand ( int max )
{
return int(myrand() * double(max));
}
编辑:这是一个简单的类,它将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);
}
};
注意:未经测试或调试。
您可以像这样使用此生成器:
BoundedRandom randomx(398);
BoundedRandom randomy(198);
// ...
xm = randomx() + 1; // 1 through 399
ym = randomy() + 1; // 1 through 199
C ++ 11引入了随机数生成器,几乎肯定会比rand做得更好。 以下是使用mersenne twister算法的示例,但根据您需要的特性,还有其他可供选择的示例。
// [1, 399]
auto random_int = std::bind(std::uniform_int_distribution<int>(1,399),std::mt19937());
// [0, 1.0)
auto random_double = std::bind(std::uniform_real_distribution<double>(0.0,1.0),std::mt19937());
rand() % 398 + 1; /*** 1 through 399 ***/
rand() % 398 + 1; /*** 1 through 399 ***/
将生成数字1到398,因为`rand() % 398
将为0-397(398%398为0)。 下一行也一样。
另外,请注意,使用具有2的恒定功率的pow
可能比简单地写出乘法花费多一个数量级的CPU,并且通常应该避免。
此外,由于你只使用rnd
与常量0.99
进行单次比较,你应该将其作为整数数学运算,因为浮点数的转换和比较将花费不仅仅是进行整数比较。 例如,两条线( rnd =
和if
)使用if((rand() % 100) == 0)
虽然略有偏差但应该准确地表明你的意图。
我已经阅读了您的代码,无法找到任何偏向右侧的内容。 如果有的话, 左边有一个统计偏差(左边三分之二应该受到0.6%ish的青睐)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.