Wie baut man aus gleichverteilen Zufallszahlen normalverteile?
Man nimmt std::normal_distribution
http://en.cppreference.com/w/cpp/numeric/random/normal_distribution
Und wie ist das Implementiert? Eine Beispielimplementation gibt es in der gnu stdc++
https://gcc.gnu.org/onlinedocs/gcc-4.7.4/libstdc++/api/a01267_source.html#l01678
Wtf? Versteht kein Mesch. Das Paper auf dass die sich beziehen ist auch ein Hammer.
http://www.eirene.de/Devroye.pdf Seite 249
Hier die Template bereinigte Version vom GNU
#include <iostream>
#include <iomanip>
#include <string>
#include <map>
#include <random>
#include <cmath>
double round(double x) {
return int(x*10)/10.0;
}
// erzeugt gleichverteilte zufallzahlen im interfall [0:1]
struct uniform_real_random_device {
std::mt19937 gen;
std::uniform_real_distribution<> uniform_dist = std::uniform_real_distribution<>(0.0, 1.0);
double operator() () {
return uniform_dist(gen);
}
};
/**
* Polar method due to Marsaglia.
*
* Devroye, L. Non-Uniform Random Variates Generation. Springer-Verlag,
* New York, 1986, Ch. V, Sect. 4.4.
*
* https://gcc.gnu.org/onlinedocs/gcc-4.7.4/libstdc++/api/a01267_source.html#l01678
*/
double normal_dist(uniform_real_random_device& rand, double mean, double stddev) {
double x, y, r2;
do
{
x = 2.0 * rand() - 1.0;
y = 2.0 * rand() - 1.0;
r2 = x * x + y * y;
}
while (r2 > 1.0 || r2 == 0.0);
double mult = std::sqrt(-2 * std::log(r2) / r2);
double result = y * mult;
result = result*stddev + mean;
return result;
}
int main() {
uniform_real_random_device uniformRand;
std::map hist;
for(int n=0; n<100000; ++n) {
double gaussZahle = normal_dist(uniformRand, 0.5, 0.5);
++hist[round(gaussZahle)];
}
// ausgabe
for(auto p : hist) {
std::cout << std::fixed << std::setprecision(1) << std::setw(2)
<< p.first << ' ' << std::string(p.second/100, '*') << '\n';
}
}
-1.5
-1.4
-1.3
-1.2
-1.1
-1.0
-0.9 *
-0.8 *
-0.7 ***
-0.6 *****
-0.5 ********
-0.4 ************
-0.3 ******************
-0.2 **************************
-0.1 **********************************
0.0 ************************************************************************************************
0.1 **************************************************************
0.2 *********************************************************************
0.3 ****************************************************************************
0.4 *******************************************************************************
0.5 *******************************************************************************
0.6 ****************************************************************************
0.7 **********************************************************************
0.8 *************************************************************
0.9 *****************************************************
1.0 *******************************************
1.1 **********************************
1.2 **************************
1.3 ******************
1.4 *************
1.5 *********
1.6 *****
1.7 ***
1.8 **
1.9 *
2.0
2.1
2.2
2.3
2.4
2.5
Jaaa da ist noch ein Bug drin bei der 0. Wer ihn findet, darf mir eine Mail schreiben.