Losowa liczba C ++ między 0 a 1

Losowa liczba C ++ między 0 a 1
Liczba losowa jest generowana w zakresie, od minimalnej liczby do maksymalnej liczby. Załóżmy, że te minimalne i maksymalne liczby są większe niż 1. Niech liczba wygenerowana w zakresie będzie nume. Niech minimalna liczba będzie min i niech maksymalna liczba będzie maksymalna. Za pomocą nich, aby przekonwertować liczbę na od 0 do 1, użyj wzoru:
Random_number = (num - min)/(max - min)

Random_number powinien być teraz od 0 do 1.
Kolejne pytania to sposób generowania liczb losowych i jak zdecydować Min i Max. W rzeczywistości liczby losowe, jak opisano w specyfikacji C ++ 20, są faktycznie pseudo-lodowatymi liczbami. Specyfikacja C ++ 20 zawiera przewodnik po tworzeniu prawdziwie losowych liczb (nieokreślone liczby losowe). Problem z tym naprawdę losowym generatorem liczb polega na tym, że odpowiedzialność kompilatora lub programista polega na dostarczeniu algorytmu do tego, co uważa się za niedeterministyczne generowanie liczb losowych. Ten artykuł nie dotyczy niedeterministycznych liczb losowych.

Liczby pseudo-lodowate są generowane w sekwencji (kolejności) liczb, które wyglądają jak liczby losowe. Wytwarzanie liczby losowej potrzebuje tak zwanego ziarna. Nasiona jest pewną wartością początkową. W tym artykule wyjaśniono podstawy generowania liczb losowych w C ++ 20. Jeśli wynikowa liczba jest większa niż 1, jest sprowadzana do od 0 do 1, przy użyciu powyższego wzoru. Biblioteka C ++ musi być uwzględniona w programie, aby mieć losową lub losową sekwencję liczbową.

Treść artykułu

  • Rozkłady
  • Linear_congruential_engine
  • Default_Random_Engine
  • Zajęcia dystrybucji liczb losowych
  • Lepsza liczba losowa
  • Wniosek

Rozkłady
Jednolity rozkład

Jednolity rozkład to taki, w którym prawdopodobieństwo liczby jest jedną z całkowitej liczby liczb w sekwencji. Rozważ następującą sekwencję:

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

Jeśli te jedenaście liczb są sekwencją liczb losowych, każda liczba pojawiła się raz z jedenastu wystąpień. Oznacza to, że jest to jednolity rozkład. W praktyce nie wszystkie mogą pojawić się raz. Jeden, dwa lub trzy mogą pojawić się więcej niż raz i nie pojawią się w regularnej kolejności.

Jeśli zwrócona liczba losowa to 40, program musi przekonwertować liczbę losową na od 0 do 1 za pomocą

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

Tutaj Num to 40; min to 0, a Max jest 100.

Rozkład dwumianowy

Rozkład dwumianowy nie jest rozkładem jednolitą. „Bi”, prefiks dwumianowego, oznacza dwa. Liczba wartości w rozkładowi dwumianowym jest reprezentowana przez T w C++. Jeśli liczby BI zainteresowane rozkładem wynoszą 2 i 3, a jeśli t wynosi 1, to sekwencja wynosi:

2, 3

Jeśli T wynosi 2 dla tych samych liczb B (2 i 3), wówczas sekwencja staje się,

4, 12, 9

Jeśli T wynosi 3 dla tych samych liczb B (2 i 3), wówczas sekwencja staje się,

8, 36, 54, 27

Jeśli T wynosi 4 dla tych samych liczb B (2 i 3), wówczas sekwencja staje się,

16, 96, 216, 216, 81

T jest pozytywną liczbą całkowitą, która może wynosić więcej niż 4. Dla każdej wartości t w sekwencji znajdują się elementy T+1. Sekwencja zależy od wybranych liczb BI i wartości t. Liczby BI mogą być dowolną parą, e.G., 13 i 17. Ważna jest również suma liczb BI. Sekwencja jest opracowana z tak zwanego twierdzenia dwumianowego.

Istnieją inne rozkłady w losowej bibliotece w C++.

Linear_congruential_engine

Istnieje wiele losowych silników liczbowych w C++. Linear_congruential_engine jest jednym z nich. Ten silnik przyjmuje nasiona, mnożą go mnożnikiem i dodaje stałą liczbę C do produktu, aby mieć pierwszą liczbę losową. Pierwsza liczba losowa staje się nowym ziarnem. To nowe ziarno jest mnożone przez to samo „a”, którego iloczyn jest dodawany do tego samego C, aby mieć drugą liczbę losową. Ta druga liczba losowa staje się nowym ziarnem dla następnej liczby losowej. Ta procedura jest powtarzana dla tak wielu liczb losowych, ile wymaga programista.

Nasiona tutaj odgrywa rolę indeksu. Domyślne ziarno to 1.

Składnia liniowego_congruential_engine to:

Linear_congruential_engineLCE

LCE to nazwa wyboru programisty. Ta składnia wykorzystuje domyślne ziarno 1. Pierwszy parametr szablonu powinien być wyspecjalizowany z „unsigned int”. Drugi i trzeci powinien mieć rzeczywiste wartości „a” i c. Czwarty powinien mieć rzeczywistą wartość oczekiwanej maksymalnej liczby losowej, plus 1.

Zakładając, że wymagane jest ziarno wartości 2, wówczas składnią byłoby:

Linear_congruential_engineLCE (2)

Zwróć uwagę na nasiona w nawiasach tuż po LCE.

Poniższy program ilustruje użycie Linear_Congruialsion_Engine, z domyślnym ziarnem 1:

#włączać
#włączać
za pomocą przestrzeni nazw Std;
int main ()

Linear_congruential_enginelce;
Cout <Cout <Cout <Cout <Cout <Cout <Cout <Cout <powrót 0;

Wyjście to:

4
13
40
121
364
0
499

Zwróć uwagę na to, w jaki sposób obiekt LCE dla silnika został utworzony. Tutaj „A” to 3, C to 1, a maksimum, mając nadzieję, że osiągnie liczbę, M wynosi 500. M jest w rzeczywistości modułem - patrz później. LCE (), jak tu używane, nie jest konstruktorem. Jest to operator, który zwraca następną liczbę losową wymaganą dla silnika w sekwencji wyjściowej. Min dla tego schematu wynosi 0, a maks. 499 i można je użyć do konwersji liczby zwróconej do 0 do 1 - patrz poniżej.

Pierwsza zwrócona liczba losowa to 4. Jest równy 1 x 3 + 1 = 4. 4 staje się nowym ziarnem. Kolejna liczba losowa to 13, co jest równe 4 x 3 + 1 = 13. 13 staje się nowym ziarnem. Następna liczba losowa to 40, co stanowi równy 13 x 3 + 1 = 40. W ten sposób kolejne liczby losowe to 121 i 364.

Poniższy kod ilustruje użycie Linear_Congruialsion_Engine, z ziarnem 2:

Linear_congruential_engineLCE (2);
Cout <Cout <Cout <Cout <Cout <Cout <Cout <Cout <

Wyjście to:

7
22
67
202
607
0
999

Maksymalna liczba losowa liczyła tutaj 1000. Min dla tego schematu jest nadal 0, a maks. 999, a można je użyć do konwersji liczby zwróconej do od 0 do 1 - patrz poniżej

Pierwsza zwrócona liczba losowa to 7. Jest równy 2 x 3 + 1 = 7. 7 staje się nowym ziarnem. Następna liczba losowa to 22, co jest równe 7 x 3 + 1 = 22. 22 staje się nowym ziarnem. Następna liczba losowa to 67, co stanowi 22 x 3 + 1 = 67. W ten sposób kolejne liczby losowe to 202 i 607.

Poniższy kod wykorzystuje powyższy wzór do wytworzenia liczby losowej między 0 a 1, dla tego silnika:

Linear_congruential_engineLCE (2);
unsigned int num = lce (); // normalna liczba losowa
niepodpisany int min = lce.min ();
niepodpisany int max = lce.Max ();
float Random_number = (float) (num - min))/(float) (max - min));
Cout <

Wyjście to:

0.00700701

Tutaj num to 7 i tak

Random_number = (7 - 0)/(999 - 0) = 7/999 = 0.00700701 zaokrąglone do 8 miejsc po przecinku.

Linear_congruential_engine nie jest jedynym wyspecjalizowanym silnikiem w losowej bibliotece; są inni.

Default_Random_Engine

To jest jak silnik ogólny. Produkuje losowe liczby. Kolejność sekwencji nie jest gwarantowana, że ​​nie jest określona. Jednak zamówienie prawdopodobnie nie jest znane przez programistę. Poniższe dwie linie pokazują, w jaki sposób można użyć tego silnika:

Random_device rd;
Default_Random_Engine eng (rd ());

Random_device to klasa, z której rd został utworzony. Zwróć uwagę na nawiasy dla RD na listach argumentów silnika. Dystrybutor potrzebuje tego silnika do działania - patrz poniżej.

Zajęcia dystrybucji liczb losowych
mundliform_int_distribution

mundliform_int_distribution
Prawdopodobieństwo wystąpienia dowolnej liczby jest 1 podzielone przez całkowitą liczbę liczb dla tej klasy. Na przykład, jeśli istnieje dziesięć możliwych numerów wyjściowych, prawdopodobieństwo wyświetlania każdej liczby wynosi 1/10. Poniższy kod to ilustruje:

Random_device rd;
Default_Random_Engine eng (rd ());
mundliform_int_distributionDist (3, 12);
Cout <Cout <

Dane wyjściowe z komputera autora to:

9 8 3 5 12
7 4 11 7 6

Niestety 7 pojawił się dwa razy na koszt 10. Argumenty Dist to liczby 3 i 13 włącznie (dziesięć kolejnych liczb całkowitych). Dist (ENG) to operator, który zwraca następny numer. Używa silnika. Zwróć uwagę na użycie specjalizacji szablonu int.

Nie ma potrzeby szukania NUM, MIN i MAX w tej sprawie, a następnie używać powyższego wzoru, aby uzyskać liczbę od 0 do 1. Dzieje się tak, ponieważ istnieje równoważny float tej klasy, który używa specjalizacji pływaków. Wyjście nie będzie takie samo dla każdego przebiegu.

mundliform_real_distribution

mundliform_real_distribution jest podobny do mundury_int_distribution. Z nim, aby uzyskać liczbę od 0 do 1, po prostu użyj 0 i 1 jako argumenty. Poniższy kod to ilustruje:

Random_device rd;
Default_Random_Engine eng (rd ());
mundliform_real_distributionDist (0, 1);
Cout <Cout <

Dane wyjściowe z komputera autora to:

0.384051 0.745187 0.364855 0.122008 0.580874
0.745765 0.0737481 0.48356 0.184848 0.745821

Zwróć uwagę na użycie specjalizacji szablonu pływaka. Wyjście nie będzie takie samo dla każdego przebiegu.

rozkład dwumianowy

Z tym rozkładem prawdopodobieństwo dla każdego numeru wyjściowego nie jest takie samo. Binomial_distribution ilustruje się powyżej. Poniższy kod pokazuje, jak używać Binomial_distribution do wytworzenia 10 losowych liczb:

Random_device rd;
Default_Random_Engine eng (rd ());
rozkład dwumianowyDist (10);
Cout <Cout <

Dane wyjściowe z komputera autora to:

5 3 5 5 7
6 6 5 8 3

Wyjście nie będzie takie samo dla każdego przebiegu. Zastosowana tutaj specjalizacja szablonu jest int int.

Poniższy kod wykorzystuje powyższy wzór do wytworzenia liczby losowej między 0 a 1 dla tego rozkładu:

Random_device rd;
Default_Random_Engine eng (rd ());
rozkład dwumianowyDist (10);
unsigned int num = dist (eng); // normalna liczba losowa
niepodpisany int min = dist.min ();
niepodpisany int max = dist.Max ();
Cout <Cout <Cout <Cout <float Random_number = (float) (num - min))/(float) (max - min));
Cout <

Dane wyjściowe z komputera autora to:

0
10
7
0.7

Lepsza liczba losowa

Liczba sekund, ponieważ epok Unix może być używany jako nasiona. Hakerowi trudno jest poznać ziarno. Poniższy program ilustruje to za pomocą linear_congruential_engine:

#włączać
#włączać
#włączać
za pomocą przestrzeni nazw Std;
int main ()

const auto p1 = chrono :: system_clock :: now ();
unsigned int seed = chrono :: czas trwania(P1.czas_since_epoch ()).liczyć();
Linear_congruential_engineLCE (ziarno);
Cout <Cout <Cout <Cout <powrót 0;

Dane wyjściowe z komputera autora to:

91 274 823 470 411
0
999

Zauważ, że uwzględniono bibliotekę Chrono. Wyjście jest inne dla każdego biegu.

Wniosek

Najłatwiejszym sposobem posiadania liczby losowej między 0 a 1 jest użycie losowego_device, default_random_engine i mundure_real_distribution (z argumentami 0 i 1). Każdy inny użyty silnik lub dystrybucja może wymagać wzoru, Random_number = (Num - min)/(Max - min).