How to use std :: normal_distribution in c ++ 11?

I want to get random floating point numbers in a range [0.0,1.0], so most of these numbers should be around 0.5. So I came up with the following function:

static std::random_device __randomDevice;
static std::mt19937 __randomGen(__randomDevice());
static std::normal_distribution<float> __normalDistribution(0.5, 1);

// Get a normally distributed float value in the range [0,1].
inline float GetNormDistrFloat()
{
    float val = -1;
    do { val = __normalDistribution(__randomGen); } while(val < 0.0f || val > 1.0f);

    return val;
}

However, calling this function 1000 times results in the following distribution:

0.0 - 0.25 : 240 times
0.25 - 0.5 : 262 times
0.5 - 0.75 : 248 times
0.75 - 1.0 : 250 times

I expected the first and last quarter of the range to appear much smaller than shown above. Therefore, it seems to me that I'm doing something wrong.

Any ideas?

+6
source share
2 answers

Short answer : do not tear off tails of normal distribution.

. , 1 [0,1]. :

enter image description here

, , , , . .

, [0,1], :

enter image description here

, wolfram alpha.

, :

#include <iostream>
#include <random>
using namespace std;

static std::random_device __randomDevice;
static std::mt19937 __randomGen(__randomDevice());
static std::normal_distribution<float> __normalDistribution(0.5, 1);

// Get a normally distributed float value in the range [0,1].
inline float GetNormDistrFloat()
{
    float val = -1;
    do { val = __normalDistribution(__randomGen); } 
    while(val < 0.0f || val > 1.0f);

    return val;
}

int main() {
    int count1=0;
    int count2=0;
    int count3=0;
    int count4=0;
    for (int i =0; i< 1000000; i++) {
        float val = GetNormDistrFloat();
        if (val<0.25){ count1++; continue;}
        if (val<0.5){ count2++; continue;}
        if (val<0.75){ count3++; continue;}
        if (val<1){ count4++; continue;}
    }
    std::cout<<count1<<", "<<count2<<", "<<count3<<", "<<count4<<std::endl;
    return 0;
}

: 0,1 : 16072 : 0

241395, 258131, 258275, 242199

( Caleth): () 1/(1 + exp (-x)), (-∞, + ∞) [ 0,1]. , .

: , , , , . 0 1, [0,1] , , +/- 4 . , 1, . .

1, ( 4 ..), , [0,1], :

val = NormalRand(0,1);
if abs(val) < 4 return val/8 + 0.5
else return UniformRand(0,1)

( interjay): .

+12

. R, ++. , , (.. ) , :

#include <random>
#include <Rcpp.h>

// [[Rcpp::plugins(cpp11)]]
// [[Rcpp::export]]
std::vector<double> getNormals(int n) {
    std::vector<double> X(n);
    std::mt19937 engine(42);
    std::normal_distribution<> normal(0.0, 1.0);
    for (int i=0; i<n; i++) {
        X[i] = normal(engine);
    }
    return X;
}

// [[Rcpp::export]]
std::vector<double> getTruncatedNormals(int n) {
    std::vector<double> X(n);
    std::mt19937 engine(42);
    std::normal_distribution<> normal(0.0, 1.0);
    int i=0;
    while (i<n) {
        double x = normal(engine);
        if (x > -0.5 && x < 0.5) {
            X[i++] = x;
        }
    }
    return X;
}


/*** R
op <- par(mfrow=c(1,2)) # two plot
x <- getNormals(1000)
hist(x, main="Normal")
z <- getTruncatedNormals(1000)
hist(z, main="Truncated")
par(op)
*/

R Rcpp Rcpp::sourceCpp("code.cpp") , ++ R . : enter image description here

, , 1/2 1.

: OP , , , , .

: n = 1e6 Normal :

enter image description here

+4

Source: https://habr.com/ru/post/1016856/


All Articles