C++ 对蒙特卡罗来说,随机性不够

C++ 对蒙特卡罗来说,随机性不够,c++,montecarlo,C++,Montecarlo,据网站介绍,我正试图用蒙特卡罗方法从正态分布生成值 我对代码进行了一些修改,使其直接计算生成的数字的方差和平均值,以检查该方法是否有效,而不是单独进行测试(实际上相同的差异,但只是一个提示) 问题 不管我做什么,方差都远远大于1,平均值不是零。有没有可能生成的伪随机数不够随机 代码 请注意,上述网站的作者就是编写代码的人 #include <cstdlib> #include <cmath> #include <ctime> #include <iost

据网站介绍,我正试图用蒙特卡罗方法从正态分布生成值

我对代码进行了一些修改,使其直接计算生成的数字的方差和平均值,以检查该方法是否有效,而不是单独进行测试(实际上相同的差异,但只是一个提示)

问题

不管我做什么,方差都远远大于1,平均值不是零。有没有可能生成的伪随机数不够随机

代码

请注意,上述网站的作者就是编写代码的人

#include <cstdlib>
#include <cmath>
#include <ctime>
#include <iostream>
using namespace std;
// return a uniformly distributed random number
double uniformRandom()
{
    return ( (double)(rand()) + 1. )/( (double)(RAND_MAX) + 1. );
}

// return a normally distributed random number
double normalRandom()
{
    double u1=uniformRandom();
    double u2=uniformRandom();
    return cos(8.*atan(1.)*u2)*sqrt(-2.*log(u1)); 
}

int main()
{
    double z;
    int N=1000;
    double array[N];
    double mean=0 ,variance=0;
    srand(time(NULL));

    for(int i=0;i<N;i++)
    {
        z=normalRandom();
        cout << i << "->"<< z<< endl;
        mean+=z;
        array[i]=z;
    }

    mean=mean/N ;
    cout << " mean = " << mean << endl;

    for(int i=0;i<N;i++)
    {
        variance = variance + (mean - array[i])*(mean - array[i]);
    }
    variance = variance/N;
    cout << " variance = " << variance << endl;

    return 0;
}
#包括
#包括
#包括
#包括
使用名称空间std;
//返回均匀分布的随机数
双uniformRandom()
{
返回((双倍)(rand())+1。)/(双倍)(rand_MAX)+1。);
}
//返回一个正态分布的随机数
双正态随机()
{
双u1=uniformRandom();
双u2=uniformRandom();
返回cos(8.*atan(1.)*u2)*sqrt(-2.*log(u1));
}
int main()
{
双z;
int N=1000;
双数组[N];
双均值=0,方差=0;
srand(时间(空));
for(int i=0;i
rand()
在大多数实现中是一个非常低质量的随机数生成器。一些Linux版本会从内核熵池中获取值,但不能保证跨平台(例如在Windows上?)使用Mersenne Twister。Boost库实现一个

编辑:taocp答案强调了一个编码问题,但RNG问题仍然适用。

rand()
在大多数实现中是一个非常低质量的随机数生成器。一些Linux版本会从内核熵池中获取值,但不能保证跨平台(例如在Windows上?)改用Mersenne扭曲器。Boost库实现一个


编辑:taocp答案突出了一个编码问题,但RNG问题仍然适用。

您似乎以错误的方式计算了
平均值。
平均值应在
N
上求平均值,而您仅对所有数组元素求和。当前
平均值实际上是

mean = mean /N

您似乎以错误的方式计算了
平均值
平均值
应在
N
上求平均值,而您仅对所有数组元素求和。当前
平均值
实际上是

mean = mean /N


感谢您指出这一点。但方差仍然远未接近1。@nerorevenge您可以尝试生成2000多个随机数,看看方差是否接近1?rand()可能不是一个好的随机数生成器(只是我的猜测)@nerorevenge:你错了。不正确的平均值会影响方差的值。在你确定平均值后,这就解决了代码中的所有问题。@nerorevenge标准偏差应该是1,而不是方差。Std.Dev=方差的平方根。@iValueValue:根据定义,如果
标准偏差=1
那么
variance=1
因为
sqrt(1)=1
1*1=1
。感谢您指出这一点。但方差仍然远未接近1。@nerorevenge您可以尝试生成2000多个随机数,看看方差是否越来越接近1?rand()可能不是一个好的随机数生成器(只是我的胡乱猜测)@nerorevenge:你错了。不正确的平均值会影响方差的值。在你确定平均值后,这就解决了代码中的所有问题。@nerorevenge标准偏差应该是1,而不是方差。Std.Dev=方差的平方根。@iValueValue:根据定义,如果
标准偏差=1
那么
variance=1因为
sqrt(1)=1
1*1=1
。注意,代码正在linux机器上运行,因此您的答案可能是正确的,让我把gback交给您。gback?无论如何,并非所有linux libc都实际使用熵池。我无法区分哪些使用,哪些不使用,但我非常确定
rand
适合玩“猜我的数字”针对PC,不是为了进行统计分析或加密。如果您使用的是最新版本的gcc,则不需要使用boost。现在,
具有所有这些功能。注意,代码正在linux机器上运行,因此您的答案可能是对的,让我把gback交给您。gback?无论如何,并非所有linux libc都实际使用熵池。我不知道该做什么和不该做什么,但我很确定,
rand
适合玩“猜猜我的数字”针对PC,不是为了进行统计分析或加密。如果您使用的是最新版本的gcc,则不需要使用boost。现在,
具有所有这些功能。我过去读过,从均匀随机数生成正态分布随机数通常不是特别准确——最好使用正态分布随机数RNG(Dunn:确切地说,在哪里找到一个。以前是一个旧的FORTRAN LIBS,但不知道C++)。@我不知道你读到哪里,但是这是一个非常不稳定的语句。正常分布的生成是均匀分布的。但是,使用一个差的均匀生成器(如<代码> RAND()。
)将导致糟糕的正态分布。@HotLicks指出,显然我为之做这件事的朋友希望这是一种蒙特卡罗方法。@MikeBantegui——就像我说的,这是“过去的”几十年前,我在想。我过去曾读过,从均匀随机中生成一个正态分布一般不是特别准确的——更好的是使用一个正态分布RNG。(虽然不知道在哪里可以找到一个。以前在Fortran LIBS中是一个,但不知道C++。)@HotLicks:我不知道你从哪里读到的,但这是一个非常不可靠的说法。从均匀分布生成正态分布是相当困难的。然而,使用一个糟糕的均匀分布