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

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.