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
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
Dazu braucht man gar kein Numpy, "normales" Python tut es auch:
1 | from random import gauss |
2 | x = gauss(0.8, 0.2) |
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 |
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. |
Vielen Dank schon einmal: habe dieses gefunden: Mittelwert * sqrt(-2 * log(rand(1,1)))*sin(2*pi*rand(1,1)) + Sigma
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.