Forum: PC-Programmierung Zufallszahlen normalverteilt generieren


von ZV (Gast)


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

von Guest (Gast)


Lesenswert?

Such nach Transformation von Zufallsvariablen.

von shfgk (Gast)


Lesenswert?

schonmal numpy angeschaut?

von random++ (Gast)


Lesenswert?


von Sven B. (scummos)


Lesenswert?

1
import numpy as np
2
import matplotlib.pyplot as plt
3
data = np.random.normal(0.8, 0.2, 1000)
4
plt.hist(data, bins=25)
5
plt.show()

: Bearbeitet durch User
von Yalu X. (yalu) (Moderator)


Lesenswert?

Dazu braucht man gar kein Numpy, "normales" Python tut es auch:
1
from random import gauss
2
x = gauss(0.8, 0.2)

von Sven B. (scummos)


Lesenswert?

Aber:
1
In [3]: timeit [gauss(0.8, 0.2) for x in range(1000)]
2
1000 loops, best of 3: 1.36 ms per loop
3
4
In [4]: timeit np.random.normal(0.8, 0.2, 1000)
5
10000 loops, best of 3: 79.4 µs per loop

von C++11 (Gast)


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.

von ZV (Gast)


Lesenswert?

Vielen Dank schon einmal:

habe dieses gefunden:

Mittelwert * sqrt(-2 * log(rand(1,1)))*sin(2*pi*rand(1,1)) + Sigma

von Yalu X. (yalu) (Moderator)


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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.