Google hat mir nichts erzählt. Vielleicht hatte ich die falschen Begriffe? Wie erzeuge ich aus einer Reihe von gleichverteilten random uint32_t Werten einen neuen random uint32_t Wert, in dessen bit-pattern Einsen mit einer Wahrscheinlichkeit p und Nullen mit einer Wahrscheinlichkeit 1-p vorkommen? Am Ende werde ich wohl ein paar Millionen dieser Zufallszahlen brauchen und p wird so gering sein, dass über all diese Zufallszahlen insgesamt nur ein paar Bits gesetzt sind. p liegt also als float vor und Geschwindigkeit wäre ein Thema. Hat schon mal jemand was über dieses Problem gelesen?
A. S. schrieb: > Wie erzeuge ich aus einer Reihe von gleichverteilten > random uint32_t Werten einen neuen random uint32_t Wert, > in dessen bit-pattern Einsen mit einer Wahrscheinlichkeit p > und Nullen mit einer Wahrscheinlichkeit 1-p vorkommen? Du erzeugst den Zielwert bitweise. Du nimmst für jeden Zielwert einen Block von 32 gleich- verteilten Zufallszahlen und vergleichst sie alle mit max_int*p. Wenn die jeweilige Zufallszahl kleiner als dieser Schwellenwert ist, setzt Du das korrespondierende Bit des Zielwertes auf 1, andernfalls auf 0. > Hat schon mal jemand was über dieses Problem gelesen? Nein -- aber Deine präzise Fragestellung suggerierte mir im zweiten Durchdenken die Antwort... HTH
1 | #include <stdio.h> |
2 | #include <stdlib.h> |
3 | #include <stdint.h> |
4 | #include <time.h> |
5 | |
6 | uint32_t generate_random_uint32_with_probability(double p) { |
7 | uint32_t result = 0; |
8 | uint32_t mask = 1; |
9 | |
10 | // Schwellenwert berechnen
|
11 | uint32_t threshold = (uint32_t)(p * (double)UINT32_MAX); |
12 | |
13 | for (int i = 0; i < 32; ++i) { |
14 | uint32_t rand_value = rand(); |
15 | |
16 | // Setze das Bit basierend auf der Wahrscheinlichkeit p
|
17 | if (rand_value <= threshold) { |
18 | result |= mask; |
19 | }
|
20 | |
21 | mask <<= 1; |
22 | }
|
23 | |
24 | return result; |
25 | }
|
26 | |
27 | int main() { |
28 | // Seed für den Zufallszahlengenerator setzen
|
29 | srand((unsigned int)time(NULL)); |
30 | |
31 | double p = 0.7; // Wahrscheinlichkeit für Einsen |
32 | |
33 | // Generiere den Zufallswert
|
34 | uint32_t random_value = generate_random_uint32_with_probability(p); |
35 | |
36 | printf("Generierter uint32_t Wert: %u\n", random_value); |
37 | |
38 | return 0; |
39 | }
|
`rand()` liefert keine richtig zufälligen Werte, hat keine schön gleichmässige Verteilung, und der ganze int Bereich wird davon meist auch nicht ausgenutzt. Also möglichst immer vermeiden. Unter Linux gibt es `/dev/urandom`, und `getrandom` in `<sys/random.h>`, die bringen gute Zufallswerte. Unter Windows gäbe es `RtlGenRandom` in der `<ntsecapi.h>`.
Daniel A. schrieb: > `rand()` liefert keine richtig zufälligen Werte, hat keine schön > gleichmässige Verteilung, und der ganze int Bereich wird davon meist > auch nicht ausgenutzt. Das kann man pauschal nicht sagen, da es von der Implementation abhängt. Echten Zufall generiert sie zwar nicht (aber es ist unklar, ob das überhaupt nötig und gewünscht ist), aber gerade die Linux-Version hat einen guten Pseudozufallsgenerator hinter rand().
Es ist in Beitrag "Re: Zufallszahl mit vorgegebener bit-Wahrscheinlichkeit" nicht erkennbar, das auf die Forderung " erzeuge aus einer Reihe von gleichverteilten Werten einen neuen Wert " eingegangen wird. Insbesonders auf Hinblick auf die Ergänzung: "p wird so gering sein, dass über all diese Zufallszahlen insgesamt nur ein paar Bits gesetzt sind." Da wird man wohl eine Routine schreiben müssen, die nur einmal initial zur Generierung der Folge den seed erzwingt und hilfreich wird es wohl sein p über die gesamte Folge (und nicht nur über 32 Zufallsereignisse) zu überwachen. Nötig wäre auch die Information über welche Mindestanzahl n von bits p ermittelt wird. Bei sehr kleinem p (bspw <0.01) wäre es auch überlegenswert, nicht für jedes bit den Zufallsgenerator anzuwerfen, sondern lediglich den Abstand zur nächsten Zufalls-'1' "auszuwürfeln". Diese Abstände dürften auch eine Zufallsreihe mit dem Erwartungswert 1/p sein.
:
Bearbeitet durch User
Rolf M. schrieb: > Daniel A. schrieb: >> `rand()` liefert keine richtig zufälligen Werte, hat keine schön >> gleichmässige Verteilung, und der ganze int Bereich wird davon meist >> auch nicht ausgenutzt. > > Das kann man pauschal nicht sagen, da es von der Implementation abhängt. > Echten Zufall generiert sie zwar nicht (aber es ist unklar, ob das > überhaupt nötig und gewünscht ist), aber gerade die Linux-Version hat > einen guten Pseudozufallsgenerator hinter rand(). Ja, ok. Hier ist RAND_MAX gleich INT_MAX, ja, vermutlich ist es hier gar nicht so schlecht. -- Der Code von Gerald hat noch einen Fehler drin, wenn man rand() nimmt. Statt UINT32_MAX sollte man RAND_MAX nehmen, und statt uint32_t einen int.
Daniel A. schrieb: > Ja, ok. Hier ist RAND_MAX gleich INT_MAX, ja, vermutlich ist es hier gar > nicht so schlecht. Intern wird wohl noch mit mehr Bits gearbeitet. Aus der man-Page: "Die Periode dieses Zufallszahlengenerators ist sehr groß, ungefähr 16 * ((2^31) - 1)."
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.