C ++ Zufallszahl zwischen 0 und 1

C ++ Zufallszahl zwischen 0 und 1
Eine Zufallszahl wird innerhalb eines Bereichs von einer Mindestzahl bis zu einer maximalen Zahl generiert. Angenommen, diese minimalen und maximalen Zahlen sind größer als 1. Lassen Sie die im Bereich erzeugte Zahl num sein. Lassen Sie die Mindestzahl min sein und die maximale Anzahl maximal sein. Verwenden Sie mit diesen, um die Nummer auf 0 und 1 zu konvertieren, die Formel:
random_number = (num - min)/(max - min)

random_number sollte jetzt zwischen 0 und 1 liegen.
Die nächsten Fragen sind, wie Sie zufällige Zahlen generieren und Min und Max entscheiden können. In der Tat sind zufällige Zahlen, wie durch C ++ 20-Spezifikation beschrieben, tatsächlich Pseudo-Random-Zahlen. Die C ++ 20-Spezifikation enthält eine Anleitung zur Erzeugung von wirklich zufälligen Zahlen (nicht deterministische Zufallszahlen). Das Problem mit diesem wirklich zufälligen Zahlengenerator ist, dass die Verantwortung des Compilers oder der Programmierer darin besteht, den Algorithmus für nicht deterministische Zufallszahlenerzeugung zu liefern. Dieser Artikel befasst sich nicht mit nicht deterministischen Zufallszahlen.

Pseudo-Random-Zahlen werden in einer Sequenz (einer Reihenfolge) von Zahlen generiert, die wie zufällige Zahlen aussieht. Die Erzeugung einer zufälligen Zahl braucht sogenannte Samen. Der Samen ist ein Startwert. Dieser Artikel erläutert die Grundlagen der Zufallszahlerzeugung in C ++ 20. Wenn die resultierende Zahl größer als 1 ist, wird sie auf zwischen 0 und 1 unter Verwendung der obigen Formel gesenkt. Die C ++ - Bibliothek muss in das Programm aufgenommen werden, um eine zufällige oder zufällige Zahlsequenz zu haben.

Artikelinhalt

  • Verteilungen
  • linear_congruential_engine
  • default_random_engine
  • Zufallszahlenverteilungsklassen
  • Bessere Zufallszahl
  • Abschluss

Verteilungen
Einheitliche Verteilung

Eine einheitliche Verteilung ist eine, bei der die Wahrscheinlichkeit einer Zahl eine der Gesamtzahl der Zahlen in der Sequenz ist. Betrachten Sie die folgende Sequenz:

0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100

Wenn diese elf Zahlen eine Folge von Zufallszahlen sind, ist jede Zahl einmal aus elf Ereignissen erschienen. Dies bedeutet, dass es sich um eine einheitliche Verteilung handelt. In der Praxis erscheinen nicht alle einmal. Ein oder zwei oder drei können mehr als einmal erscheinen, und sie würden nicht in regelmäßiger Reihenfolge erscheinen.

Wenn die zurückgegebene Zufallszahl 40 beträgt, muss das Programm die Zufallszahl auf zwischen 0 und 1 konvertieren

random_number = (40 - 0)/(100 - 0)
= 4/10 = 0.4

Hier ist Num 40; min ist 0 und max ist 100.

Binomiale Verteilung

Die Binomialverteilung ist keine einheitliche Verteilung. "Bi", das Präfix von Binomial, bedeutet zwei. Die Anzahl der Werte in der Binomialverteilung wird durch t in C dargestellt++. Wenn die für die Verteilung betroffenen BI -Zahlen 2 und 3 betragen und wenn t 1 ist, dann ist die Sequenz:

2, 3

Wenn t 2 für die gleichen BI -Zahlen (2 und 3) ist, wird die Sequenz,

4, 12, 9

Wenn t 3 für die gleichen BI -Zahlen (2 und 3) 3 ist, wird die Sequenz,

8, 36, 54, 27

Wenn t 4 für die gleichen Bi -Zahlen (2 und 3) 4 ist, wird die Sequenz,

16, 96, 216, 216, 81

T ist eine positive Ganzzahl, die mehr als 4 betragen kann. Für jeden Wert von t gibt es T+1 -Elemente in der Sequenz. Eine Sequenz hängt von den ausgewählten BI -Zahlen und dem Wert von t ab. Die BI -Zahlen können jedes Paar sein, e.G., 13 und 17. Die Summe der BI -Zahlen ist ebenfalls wichtig. Eine Sequenz wird aus dem sogenannten Binomialsatz entwickelt.

Es gibt andere Verteilungen in der zufälligen Bibliothek in C++.

linear_congruential_engine

Es gibt eine Reihe von Motoren mit Zufallszahl in C++. linear_congruential_engine ist einer von ihnen. Dieser Motor nimmt einen Saatgut, multipliziert ihn mit einem Multiplikator und fügt dem Produkt eine konstante Zahl C hinzu, um die erste Zufallszahl zu haben. Die erste Zufallszahl wird zum neuen Samen. Dieser neue Saat. Diese zweite Zufallszahl wird zum neuen Saatgut für die nächste Zufallszahl. Dieser Vorgang wird für so viele Zufallszahlen wiederholt, wie vom Programmierer erforderlich.

Der Saatgut hier hat die Rolle eines Index. Der Standardsamen ist 1.

Eine Syntax für die linear_congruential_engine ist:

linear_congruential_enginelce

LCE ist der Name der Wahl des Programmierers. Diese Syntax verwendet den Standardsamen von 1. Der erste Vorlagenparameter hier sollte mit „nicht signiertem int“ spezialisiert sein. Der zweite und dritte sollte die tatsächlichen Werte von 'a' und c haben. Der vierte sollte den tatsächlichen Wert der erwarteten maximalen Zufallszahl plus 1 haben.

Unter der Annahme, dass ein Samen des Wertes 2 erforderlich ist, wäre die Syntax:

linear_congruential_enginelce (2)

Beachten Sie den Samen in Klammern kurz nach LCE.

Das folgende Programm veranschaulicht die Verwendung von linear_congruential_engine mit dem Standard -Samen von 1:

#enthalten
#enthalten
Verwenden von Namespace STD;
int main ()

linear_congruential_enginelce;
Cout <Cout <Cout <Cout <Cout <Cout <Cout <Cout <Rückkehr 0;

Die Ausgabe ist:

4
13
40
121
364
0
499

Beachten Sie, wie das LCE -Objekt für den Motor instanziiert wurde. Hier, 'a' ist 3, c ist 1 und das Maximum hoffte, die Zahl zu erreichen, M beträgt 500. M ist eigentlich ein Modul - später siehe. LCE (), wie hier verwendet, ist kein Konstruktor. Es ist ein Bediener, der die nächste Zufallszahl zurückgibt, die für den Motor in der Ausgangssequenz erforderlich ist. min für dieses Schema ist 0 und max ist 499, und diese können verwendet werden, um eine Zahl zwischen 0 und 1 zu konvertieren - siehe unten.

Die erste zurückgegebene zufällige Zahl beträgt 4. Es entspricht 1 x 3 + 1 = 4. 4 wird zum neuen Samen. Die nächste Zufallszahl ist 13, was gleich 4 x 3 + 1 = 13 entspricht. 13 wird zum neuen Samen. Die nächste Zufallszahl ist 40, was gleich 13 x 3 + 1 = 40 entspricht. Auf diese Weise betragen die nachfolgenden Zufallszahlen 121 und 364.

Der folgende Code veranschaulicht die Verwendung von linear_congruential_engine mit einem Samen von 2:

linear_congruential_enginelce (2);
Cout <Cout <Cout <Cout <Cout <Cout <Cout <Cout <

Die Ausgabe ist:

7
22
67
202
607
0
999

Die maximale Zufallszahl, die hier erhofft wurde. min für dieses Schema ist immer noch 0 und Max ist jetzt 999, und diese können verwendet werden, um eine Zahl zwischen 0 und 1 zu konvertieren - siehe unten

Die erste zurückgegebene Zufallszahl ist 7. Es entspricht 2 x 3 + 1 = 7. 7 wird zum neuen Samen. Die nächste Zufallszahl ist 22, was gleich 7 x 3 + 1 = 22 entspricht. 22 wird zum neuen Samen. Die nächste Zufallszahl ist 67, was 22 x 3 + 1 = 67 entspricht. Auf diese Weise sind die nachfolgenden Zufallszahlen 202 und 607.

Der folgende Code verwendet die obige Formel, um eine Zufallszahl zwischen 0 und 1 für diese Engine zu erzeugen:

linear_congruential_enginelce (2);
nicht signiert int num = lce (); // normale Zufallszahl
nicht signiert int min = lce.Mindest();
nicht signiert int max = lce.max ();
float random_number = ((float) (num - min))/((float) (max - min));
Cout <

Die Ausgabe ist:

0.00700701

Hier ist Num 7 und so

random_number = (7 - 0)/(999 - 0) = 7/999 = 0.00700701 auf 8 Dezimalstellen abgerundet.

linear_congruential_engine ist nicht die einzige spezialisierte Engine in der Zufallsbibliothek. Da sind andere.

default_random_engine

Dies ist wie ein allgemeiner Motor. Es erzeugt zufällige Zahlen. Die Reihenfolge ist garantiert nicht festgelegt. Der Programmierer ist jedoch wahrscheinlich nicht bekannt. Die folgenden zwei Zeilen zeigen, wie dieser Motor verwendet werden kann:

Random_Device Rd;
default_random_engine eng (rd ());

Random_Device ist eine Klasse, aus der die RD instanziiert wurde. Beachten Sie die Klammern für RD in den Argument -Listen des Motors. Ein Händler benötigt diesen Motor für seinen Betrieb - siehe unten.

Zufallszahlenverteilungsklassen
Uniform_int_distribution

Uniform_int_distribution
Die Wahrscheinlichkeit, dass eine beliebige Zahl auftritt, ist 1 geteilt durch die Gesamtzahl der Zahlen für diese Klasse. Wenn beispielsweise zehn mögliche Ausgangsnummern vorhanden sind, beträgt die Wahrscheinlichkeit jeder angezeigten Zahl 1/10. Der folgende Code zeigt dies:

Random_Device Rd;
default_random_engine eng (rd ());
Uniform_int_distributionDist (3, 12);
Cout <Cout <

Die Ausgabe vom Computer des Autors lautet:

9 8 3 5 12
7 4 11 7 6

Leider ist 7 zweimal auf Kosten von 10 erschienen. Die Argumente von Dist sind die Zahlen 3 und 13 inklusive (zehn aufeinanderfolgende ganze Zahlen). Dist (ENG) ist ein Betreiber, der die nächste Nummer zurückgibt. Es verwendet den Motor. Beachten Sie die Verwendung der Int -Vorlagespezialisierung.

Für diesen Fall besteht keine Notwendigkeit, nach Num, Min und Max zu suchen und dann die obige Formel zu verwenden, um eine Zahl zwischen 0 und 1 zu erhalten. Dies liegt daran. Die Ausgabe ist für jeden Lauf nicht gleich.

EINFALIERT

Uniform_real_distribution ist ähnlich wie bei Uniform_int_distribution. Verwenden Sie damit nur 0 und 1 als Argumente, um eine Zahl zwischen 0 und 1 zu erhalten. Der folgende Code zeigt dies:

Random_Device Rd;
default_random_engine eng (rd ());
EINFALIERTdist (0, 1);
Cout <Cout <

Die Ausgabe vom Computer des Autors lautet:

0.384051 0.745187 0.364855 0.122008 0.580874
0.745765 0.0737481 0.48356 0.184848 0.745821

Beachten Sie die Verwendung der Float -Vorlagespezialisierung. Die Ausgabe ist für jeden Lauf nicht gleich.

Binomial_Distribution

Mit dieser Verteilung ist die Wahrscheinlichkeit für jede Ausgabennummer nicht gleich. Binomial_distribution wurde oben dargestellt. Der folgende Code zeigt, wie die Binomial_Distribution verwendet wird, um 10 Zufallszahlen zu erzeugen:

Random_Device Rd;
default_random_engine eng (rd ());
Binomial_DistributionDist (10);
Cout <Cout <

Die Ausgabe vom Computer des Autors lautet:

5 3 5 5 7
6 6 5 8 3

Die Ausgabe ist für jeden Lauf nicht gleich. Die hier verwendete Vorlagenspezialisierung ist int int.

Der folgende Code verwendet die obige Formel, um eine Zufallszahl zwischen 0 und 1 zu erzeugen, für diese Verteilung:

Random_Device Rd;
default_random_engine eng (rd ());
Binomial_DistributionDist (10);
nicht signiert int num = dist (ENG); // normale Zufallszahl
unsigned int min = dist.Mindest();
nicht signiert int max = dist.max ();
Cout <Cout <Cout <Cout <float random_number = ((float) (num - min))/((float) (max - min));
Cout <

Die Ausgabe vom Computer des Autors lautet:

0
10
7
0.7

Bessere Zufallszahl

Die Anzahl der Sekunden seit der UNIX -Epoche kann als Samen verwendet werden. Für den Hacker wird es schwierig, den Samen zu kennen. Das folgende Programm zeigt dies mit der linear_congruential_engine:

#enthalten
#enthalten
#enthalten
Verwenden von Namespace STD;
int main ()

const auto p1 = chrono :: system_clock :: jetzt ();
nicht signiert int Seed = chrono :: duration_cast(P1.Time_Since_epoch ()).zählen();
linear_congruential_engineLCE (Samen);
Cout <Cout <Cout <Cout <Rückkehr 0;

Die Ausgabe vom Computer des Autors lautet:

91 274 823 470 411
0
999

Beachten Sie, dass die Chrono -Bibliothek aufgenommen wurde. Die Ausgabe ist für jeden Lauf unterschiedlich.

Abschluss

Der einfachste Weg, eine zufällige Zahl zwischen 0 und 1 zu haben, besteht darin, den Random_Device, die default_random_engine und die Uniform_real_distribution zu verwenden (mit Argumenten 0 und 1). Jeder andere Motor oder eine andere verwendete Verteilung muss die Formel benötigen, random_number = (num - min)/(max - min).