Zufallszahlen normalverteilt generieren

Gast #4249173
Lesenswert?
• ▲
▼
Tag zusammen,

ich weiss nicht genau ob mein Problem hier hingehört, aber vllt. tummeln 
sich hier ja einige Mathe Talente in dem Forum.

Ich würde gerne Zufallszahlen generieren, die normalverteilt sind. Ein 
konkretes Beispiel:

Ich habe eine Waage die für eine bestimmte Anzahl von Ziehungen N mit 
dem selben Gewicht im Schnitt 1 Kg misst.

Ich weiss, dass die Standardabweichung dieser Messung z.B. 0,2 kg 
beträgt (d.h. Sigma = 0,2).

Die Dichtefunktion dieser Normalverteilung kann ich ja ohne weiteres mit 
Mittelwert (mu = 1 kg) und Standardabweichung (Sigma = 0,2) 
implementieren. Diese müsste einen Peak bei dem Mittelwert haben (also 
0,8), da dieser Wert normalverteilt der wahrscheinlichste ist.

Ich hoffe soweit sind meine Überlegungen richtig?

Jetzt möchte ich aber Zufallszahlen generieren, die eben genau dieser 
Normalverteilungen folgen (mit der Standardabweichung 0,2). D.h. am 
häufigsten sollte ich die ZV 0,8 herausbekommen, aber eben nicht immer, 
sondern die Zahl die rauskommt soll der Normalverteilung entsprechen.

Ich hoffe ich habe das Problem hinreichend geschildert :)

Wie macht man so was (gerne auch in Matlab) oder auf MCU.

Danke
Gast #4249319
Lesenswert?
• ▲
▼
Kannichschnella:

1
#include <random>
2
#include <vector>
3
#include <algorithm>
4
#include <iostream>
5
#include <iomanip>
6
 
7
int const width = 30;
8
int const samples = 50000;
9
double const stretch = 20.;
10
 
11
int main(int argc, char * argv[])
12
{
13
  std::mt19937 gen;
14
  std::normal_distribution<> dist(0.8, 0.2);
15
 
16
  std::vector<unsigned> hist(width);
17
 
18
  for(size_t i = 0; i < samples; ++i)
19
  {
20
    int v = dist(gen) * stretch;
21
    if(v > 0 && v < width)
22
      ++hist[v];
23
  }
24
 
25
  int fakt = *std::max_element(hist.begin(), hist.end()) / width;
26
 
27
  for(size_t i = 0; i < width; ++i)
28
    std::cout << std::setw(4) << i / stretch << ": " << std::string(hist[i] / fakt, '*') << '\n';
29
}

--> http://ideone.com/4v3r9R
1
50000 loops in 0.00170069 seconds - 0.0340139 microseconds per sample.
Moderator #4249530
Lesenswert?
• ▲
▼
ZV schrieb:
> Mittelwert * sqrt(-2 * log(rand(1,1)))*sin(2*pi*rand(1,1)) + Sigma

Ja, so kannst du das machen, wenn du es lieber selber programmieren
möchtest.

Du kannst mit der gleichen Formel einen zweiten Zufallswert berechnen,
wenn du darin den sin-Aufruf durch einen cos-Aufruf ersetzt. So kannst
du jeden zweiten Aufruf von sqrt, log und rand einsparen, was die Sache
schneller macht. Siehe Methode von Box und Muller:

  https://de.wikipedia.org/wiki/Box-Muller-Methode

Die Box-Muller-Methode wird u.a. im random-Modul von Python benutzt.

Im Mittel noch schneller geht es mit der Polar-Methode von Marsaglia, da
hier sogar auf die trigonometrischen Funktionen verzichtet wird:

  https://de.wikipedia.org/wiki/Polar-Methode

Da diese Methode aber eine Schleife enthält, deren Abbruchbedingung von
Zufallszahlen abhängt, kann ihre Ausführung theoretisch beliebig lange
dauern, weswegen man sie nicht in Echtzeitsystemen einsetzen sollte.

Die Polar-Methode wird u.a. in der C++-Bibliothekt vom GCC eingesetzt.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren