it-swarm.com.de

Warum scheint C ++ Rand () nur Zahlen der gleichen Größenordnung zu erzeugen?

In einer kleinen Anwendung, die in C/C++ geschrieben wurde, habe ich ein Problem mit der Funktion Rand und möglicherweise dem Startwert:

Ich möchte eine Folge von Zufallszahlen erzeugen, die von unterschiedlicher Ordnung sind, d. H. Mit unterschiedlichen Logarithmuswerten (Basis 2). Aber es scheint, dass alle produzierten Zahlen in der gleichen Größenordnung sind und nur zwischen 2 ^ 25 und 2 ^ 30 schwanken.

Liegt es daran, dass Rand() mit Unix-Zeit geimpft ist, die mittlerweile eine relativ große Zahl ist? Was vergesse ich? Ich säte Rand() nur einmal am Anfang von main().

146

Es gibt nur 3% der Zahlen zwischen 1 und 230 die sind NICHT zwischen 225 und 230. Das klingt also ziemlich normal :)

Weil 225 / 230 = 2-5 = 1/32 = 0,03125 = 3,125%

478
C4stor

Das hellere Grün ist der Bereich zwischen 0 und 225; Das dunklere Grün ist der Bereich zwischen 225 und 230. Die Häkchen sind Zweierpotenzen.

distribution

272
Casey Chu

Sie müssen genauer sein: Sie möchten unterschiedliche Logarithmuswerte zur Basis 2, aber was Verteilung möchten Sie dafür? Die Standardfunktionen von Rand () erzeugen eine gleichmäßige Verteilung. Sie müssen diese Ausgabe mit der Funktion Quantil transformieren, die der gewünschten Verteilung zugeordnet ist.

Wenn Sie uns die Verteilung mitteilen, können wir Ihnen die quantile -Funktion mitteilen, die Sie benötigen.

42
Bathsheba

Wenn Sie verschiedene Größenordnungen wünschen, probieren Sie einfach pow(2, Rand()) aus. Oder wählen Sie die Reihenfolge direkt als Rand (), wie Harold vorgeschlagen hat?

18
aspiring_sarge

Die grundlegende (und korrekte) Antwort wurde bereits oben gegeben und akzeptiert: Es gibt 10 Zahlen zwischen 0 und 9, 90 Zahlen zwischen 10 und 99, 900 zwischen 100 und 999 usw.

Um eine Verteilung mit ngefähr logarithmischer Verteilung rechnerisch effizient zu erhalten, möchten Sie Ihre Zufallszahl um eine Zufallszahl nach rechts verschieben:

s = Rand() & 31; // a random number between 0 and 31 inclusive, assuming Rand_MAX = 2^32-1
r = Rand() >> s; // right shift

Es ist nicht perfekt, aber es ist viel schneller als das Berechnen von pow(2, Rand()*scalefactor). Es ist "klumpig" in dem Sinne, dass die Verteilung für Zahlen innerhalb eines Faktors 2 gleichmäßig ist (gleichmäßig für 128 bis 255, die Hälfte der Dichte für 256 bis 1023 usw.).

Hier ist ein Histogramm der Häufigkeit der Zahlen 0 bis 31 (in 1M-Samples):

enter image description here

13
Floris

@ C4stor machte einen tollen Punkt. Für einen allgemeineren und für den Menschen verständlicheren Fall (Basis 10): Für den Bereich von 1 bis 10 ^ n liegen ~ 90% der Zahlen zwischen 10 ^ (n-1) und 10 ^ n. ~ 99% der Zahlen reichen von 10 ^ (n-2) bis 10 ^ n. Fügen Sie so viele Dezimalstellen hinzu, wie Sie möchten.

Lustige Mathematik, wenn Sie dies für n weitermachen, können Sie sehen, dass von 1 bis 10 ^ n 99,9999 ...% = 100% der Zahlen von 10 ^ 0 bis 10 ^ n mit sind diese Methode.

Nun zum Code: Wenn Sie eine Zufallszahl mit zufälligen Größenordnungen von 0 bis 10 ^ n möchten, können Sie Folgendes tun:

  1. Erzeugen Sie eine kleine Zufallszahl von 0 bis n

  2. Wenn Sie den Bereich kennen, den n hat, erzeugen Sie eine große Zufallszahl der Ordnung 10 ^ k, wobei k> max {n} ist.

  3. Schneiden Sie die längere Zufallszahl ab, um die n Stellen dieser großen Zufallszahl zu erhalten.

13

Es gibt genau die gleiche Anzahl von Zahlen zwischen 0 und 2 ^ 29 und 2 ^ 29 und 2 ^ 30.

Eine andere Sichtweise auf das Problem: Betrachten Sie die binäre Darstellung der von Ihnen generierten Zufallszahl, die Wahrscheinlichkeit, dass das höchste Bit 1 ist, ist gleich 1/2, und daher erhalten Sie in halben Fällen die Ordnung 29. Was Sie wollen, ist, eine Zahl zu sehen, die unter 2 ^ 25 liegt, aber das bedeutet, dass 5 höchste Bits alle Null sind, was mit einer geringen Wahrscheinlichkeit von 1/32 geschieht. Die Wahrscheinlichkeit ist hoch, dass selbst wenn Sie es über einen längeren Zeitraum laufen lassen, Sie die Reihenfolge nie unter 15 sehen werden (die Wahrscheinlichkeit ist so etwas wie 6 6-mal hintereinander rollen).

Nun der Teil Ihrer Frage zum Samen. Nein, der Startwert kann möglicherweise nicht den Bereich bestimmen, aus dem die Zahlen generiert werden. Er bestimmt lediglich das erste Anfangselement. Stellen Sie sich Rand () als eine Folge aller möglichen Zahlen im Bereich vor (vorgegebene Permutation). Der Startwert bestimmt, wo Sie mit dem Zeichnen von Zahlen aus der Sequenz beginnen. Wenn Sie (Pseudo-) Zufälligkeit wünschen, verwenden Sie daher die aktuelle Zeit, um die Sequenz zu initialisieren: Es ist Ihnen egal, dass die Position, von der Sie ausgehen, nicht gleichmäßig verteilt ist. Es kommt nur darauf an, dass Sie nie von derselben Position ausgehen.

5
Vadim

benutze pow(2,Rand()) es gibt die Antworten in der gewünschten Größenordnung !!

2
Shivendra

Wenn Sie Zufallszahlen aus einem Onlinedienst verwenden möchten, für den Sie wget verwenden können, möchten Sie möglicherweise auch Dienste wie random.org für die Generierung von Zufallszahlen verwenden, die Sie mit wget abfangen und dann aus den Zahlen lesen können die heruntergeladene Datei

wget -q https://www.random.org/integers/?num=100&min=1&max=100&col=5&base=10&format=html&rnd=new -O new.txt

http://programmingconsole.blogspot.in/2013/11/a-better-and-different-way-to-generate.html

2
Namit Sinha