Box muller分布

时间:2016-12-18 18:56:20

标签: c# c++

2个均匀分布的数字放入框muller,得到正态分布,输出只有y小于x,当它应该介于0和1之间时,是否有任何建议?

#define _USE_MATH_DEFINES
#include <iostream>
#include <cmath>
#include <math.h>

using namespace std;

#define M 4294967295
double u1, u2, Z;


unsigned long get_rand(unsigned long x)
//establishing function to generate random numbers
{
unsigned long a = 2269477;
unsigned long b = 1;
//Values taken from wikipedia for Linear Congruence Method
unsigned long m = M;
unsigned long y;
y = (a * x + b) % m;
return y;
}

unsigned long get_normal(double x1, double x2)
{
double R,phi, u;
R = sqrt(-2 * log(x1))*cos(2 * M_PI*x2);;
//Box-Muller Transform

return R;
}

double bin0 = 0;
double bin1 = 0;
double bin2 = 0;  //Variables used to store frequency of each number range
double bin3 = 0;
double bin4 = 0;
double bin5 = 0;
double bin6 = 0;
double bin7 = 0;
double bin8 = 0;
double bin9 = 0;

int  main() {
double seed1,seed2;
cout << "Please enter seed values " << endl;
cin >> seed1;
cout << "\n";
cin >> seed2;
double x;
cout << "Please enter how many random numbers you want " << endl;
cin >> x;
cout << endl;
cout << "Random Numbers generated shown below: " << endl;


for (int i = 0; i < x; i++)
//generate as many random numbers as the user has asked for 
{
seed1 = get_rand(seed1);
seed2 = get_rand(seed2);

u1 = (double(seed1) / M);
//changing to double and dividing by 'M' gets all values between 0 and 1
cout <<"U1 = " << u1 << endl;
//type conversion to prevent integer rounding in division
u2 = (double(seed2) / M);
cout << "U2 = " << u2 << endl;

Z = get_normal(u1, u2);
cout <<"Z = " << Z << endl;

if (Z >= 0.0 && Z <= 0.1)
{
//checking for which intervals each random number falls into
bin0++;
//if a number falls into this interval, increment the counter by 1 each time
}

else if (Z > 0.1 && Z <= 0.2)
//if it doesnt fall into first interval, it will check the next interval, and so on...
{
bin1++;
}

else if (Z > 0.2 && Z <= 0.3)
{
bin2++;
}

else if (Z > 0.3 && Z <= 0.4)
{
bin3++;
}

else if (Z > 0.4 && Z <= 0.5)
{
bin4++;
}

else if (Z > 0.5 && Z <= 0.6)
{
bin5++;
}

else if (Z > 0.6 && Z <= 0.7)
{
bin6++;
}

else if (Z > 0.7 && Z <= 0.8)
{
bin7++;
}

else if (Z > 0.8 && Z <= 0.9)
{
bin8++;
}

else if (Z > 0.9 && Z <= 1.0)
{
bin9++;
}
}

double binTotal = bin0 + bin1 + bin2 + bin3 + bin4 + bin5 + bin6 + bin7 + bin8 + bin9;
cout << endl;

int bin0Percent = (bin0 / binTotal) * 100;
   //working out a percentage 
cout << " Number of values in range 0.0-0.1:      " << bin0 << endl;
//output screen for each interval
cout << " Percentage of values in this interval:   " << bin0Percent << "%" << endl;
cout << endl;

int bin1Percent = (bin1 / binTotal) * 100;
cout << " Number of values in range 0.1-0.2:      " << bin1 << endl;
cout << " Percentage of values in this interval:   " << bin1Percent << "%" << endl;
cout << endl;

int bin2Percent = (bin2 / binTotal) * 100;
cout << " Number of values in range 0.2-0.3:      " << bin2 << endl;
cout << " Percentage of values in this interval:   " << bin2Percent << "%" << endl;
cout << endl;

int bin3Percent = (bin3 / binTotal) * 100;
cout << " Number of values in range 0.3-0.4:      " << bin3 << endl;
cout << " Percentage of values in this interval:   " << bin3Percent << "%" << endl;
cout << endl;

int bin4Percent = (bin4 / binTotal) * 100;
cout << " Number of values in range 0.4-0.5:      " << bin4 << endl;
cout << " Percentage of values in this interval:   " << bin4Percent << "%" << endl;
cout << endl;

int bin5Percent = (bin5 / binTotal) * 100;
cout << " Number of values in range 0.5-0.6:      " << bin5 << endl;
cout << " Percentage of values in this interval:   " << bin5Percent << "%" << endl;
cout << endl;

int bin6Percent = (bin6 / binTotal) * 100;
cout << " Number of values in range 0.6-0.7:      " << bin6 << endl;
cout << " Percentage of values in this interval:   " << bin6Percent << "%" << endl;
cout << endl;

int bin7Percent = (bin7 / binTotal) * 100;
cout << " Number of values in range 0.7-0.8:      " << bin7 << endl;
cout << " Percentage of values in this interval:   " << bin7Percent << "%" << endl;
cout << endl;

int bin8Percent = (bin8 / binTotal) * 100;
cout << " Number of values in range 0.8-0.9:      " << bin8 << endl;
cout << " Percentage of values in this interval:   " << bin8Percent << "%" << endl;
cout << endl;

int bin9Percent = (bin9 / binTotal) * 100;
cout << " Number of values in range 0.9-1.0:      " << bin9 << endl;
cout << " Percentage of values in this interval:   " << bin9Percent << "%" << endl;
cout << endl;
}

1 个答案:

答案 0 :(得分:0)

请尝试以下方式:

#include <random>
#include <iostream>
int main()
{
    using namespace std;
    const double PI = 3.1415926535897;
    double seed1, seed2;
    cout << "Please enter seed values " << endl;
    cin >> seed1;
    cout << "\n";
    cin >> seed2;
    unsigned int nb_numbers;
    cout << "Please enter how many random numbers you want " << endl;
    cin >> nb_numbers;
    cout << endl;
    cout << "Random Numbers generated shown below: " << endl;
    std::default_random_engine generator_1(seed1),generator_2(seed2);
    std::uniform_real_distribution<double> distribution(0.0, 1.0);
    const unsigned int nb_intervals = 10;// [0,1]
    unsigned int z_values_distributed[nb_intervals] = { 0 };
    std::cout << std::fixed; std::cout.precision(1);
    unsigned int i = 0;
    unsigned int m = 0;
    while (i < nb_numbers)
    {
        double real_1 = distribution(generator_1);
        double real_2 = distribution(generator_2);
        double Z;
        m % 2 ? Z = sqrt(-2 * log(real_1))*cos(2 * PI*real_2) : Z = sqrt(-2 * log(real_1))*sin(2 * PI*real_2); //sigma=1 mu=0
        //using 10 intervals from 0 to +1 with width of 0.1 ==> 0 0.1 0.2 ..... 0.9 1.
         if (Z >= 0 && int(10 * Z) < 10)
        {
            ++i;
            ++z_values_distributed[int(10 * Z)];
        }
        ++m;
    }
    for (unsigned int i = 0; i < nb_intervals; ++i)
    {
            std::cout << "[" << (i / 10.) << "-" << ((i + 1) / 10.) << "]  : " << z_values_distributed[i] << std::endl;
    }
    return 0;
}