C ++ tilfeldig tall mellom 0 og 1

C ++ tilfeldig tall mellom 0 og 1
Et tilfeldig tall genereres innen et område, fra et minimumstall til et maksimum antall. Anta at disse minimums- og maksimumstallene er større enn 1. La antallet generert innenfor området være NUM. La minimumstallet være min, og la det maksimale antallet være maksimalt. Med disse, for å konvertere tallet til mellom 0 og 1, bruk formelen:
random_number = (num - min)/(maks - min)

Random_number skal nå være mellom 0 og 1.
De neste spørsmålene er hvordan du genererer tilfeldige tall og hvordan du bestemmer Min og Max. Faktisk er tilfeldige tall, som beskrevet av C ++ 20-spesifikasjonen, faktisk pseudo-tilfeldige tall. C ++ 20-spesifikasjonen gir en guide til å produsere virkelig tilfeldige tall (ikke-deterministiske tilfeldige tall). Problemet med denne virkelig tilfeldige tallgeneratoren er at kompilatorens ansvar, eller programmereren, er å gi algoritmen til det som anses som ikke-deterministisk tilfeldig antall generering. Denne artikkelen adresserer ikke nondeterministiske tilfeldige tall.

Pseudo-tilfeldige tall genereres i en sekvens (en rekkefølge) av tall, som ser ut som tilfeldige tall. Generering av et tilfeldig tall trenger det som kalles et frø. Frøet er noe startverdi. Denne artikkelen forklarer det grunnleggende om generering av tilfeldig tall i C ++ 20. Hvis det resulterende antallet er større enn 1, blir det brakt ned til mellom 0 og 1 ved å bruke ovennevnte formel. C ++ biblioteket må inkluderes i programmet for å ha en tilfeldig eller tilfeldig tallsekvens.

Artikkelinnhold

  • Distribusjoner
  • linear_congruential_engine
  • standard_random_engine
  • Tilfeldige tallfordelingsklasser
  • Bedre tilfeldig tall
  • Konklusjon

Distribusjoner
Uniform distribusjon

En enhetlig fordeling er en der sannsynligheten for et tall er en av det totale antall tall i sekvensen. Tenk på følgende sekvens:

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

Hvis disse elleve tallene er en sekvens av tilfeldige tall, har hvert tall dukket opp en gang ut av elleve forekomster. Dette betyr at det er en enhetlig fordeling. I praksis kan ikke alle vises en gang. En eller to eller tre kan vises mer enn en gang, og de vil ikke vises i regelmessig orden.

Hvis det tilfeldige antallet som returneres er 40, må programmet konvertere det tilfeldige tallet til mellom 0 og 1 ved bruk av

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

Her er NUM 40; min er 0, og maks er 100.

Binomial distribusjon

Binomialfordelingen er ikke en enhetlig fordeling. “Bi”, prefikset til binomial, betyr to. Antall verdier i binomialfordelingen er representert av T i C++. Hvis de berørte BI -tallene for distribusjonen er 2 og 3, og hvis t er 1, er sekvensen:

2, 3

Hvis t er 2 for de samme BI -tallene (2 og 3), blir sekvensen,

4, 12, 9

Hvis t er 3 for de samme BI -tallene (2 og 3), blir sekvensen,

8, 36, 54, 27

Hvis t er 4 for de samme BI -tallene (2 og 3), blir sekvensen,

16, 96, 216, 216, 81

T er et positivt heltall som kan være mer enn 4. For hver verdi av T er det T+1 -elementer i sekvensen. En sekvens avhenger av de valgte bi -tallene og verdien av t. BI -tallene kan være et hvilket som helst par, e.g., 13 og 17. Summen av BI -tallene er også viktig. En sekvens er utviklet fra det som er kjent som binomial teorem.

Det er andre distribusjoner i det tilfeldige biblioteket i C++.

linear_congruential_engine

Det er en rekke tilfeldige tallmotorer i C++. linear_congruential_engine er en av dem. Denne motoren tar et frø, multipliserer det med en multiplikator, og legger til et konstant tall C til produktet for å ha det første tilfeldige tallet. Det første tilfeldige tallet blir det nye frøet. Dette nye frøet multipliseres med det samme 'A', hvis produkt legges til samme C, for å ha det andre tilfeldige tallet. Dette andre tilfeldige tallet blir det nye frøet for neste tilfeldige nummer. Denne prosedyren gjentas for så mange tilfeldige tall som kreves av programmereren.

Frøet her har rollen som en indeks. Standardfrøet er 1.

En syntaks for lineær_congruential_engine er:

linear_congruential_engineLCE

LCE er navnet på programmererens valg. Denne syntaksen bruker standardfrøet på 1. Den første malparameteren her skal være spesialisert med "usignert int". Den andre og tredje skal ha de faktiske verdiene 'A' og C. Den fjerde skal ha den faktiske verdien av det maksimale tilfeldige antallet forventet, pluss 1.

Forutsatt at det er nødvendig med et frø av verdien 2, vil syntaksen være:

linear_congruential_engineLCE (2)

Legg merke til frøet i parenteser like etter LCE.

Følgende program, illustrerer bruken av linear_congruential_engine, med standardfrø på 1:

#inkludere
#inkludere
ved hjelp av navneområdet STD;
int main ()

linear_congruential_engineLCE;
cout <cout <cout <cout <cout <cout <cout <cout <retur 0;

Utgangen er:

4
1. 3
40
121
364
0
499

Legg merke til hvordan LCE -objektet for motoren ble instantiert. Her, 'A' er 3, C er 1, og det maksimale, håpet å nå antall, M er 500. M er faktisk en modul - se senere. LCE (), som brukt her, er ikke en konstruktør. Det er en operatør som returnerer det neste tilfeldige tallet som kreves for motoren i utgangssekvensen. Min for denne ordningen er 0, og Max er 499, og disse kan brukes til å konvertere et tall som returneres til mellom 0 og 1 - se nedenfor.

Det første tilfeldige tallet som er returnert er 4. Det er lik 1 x 3 + 1 = 4. 4 blir det nye frøet. Det neste tilfeldige tallet er 13, som er lik 4 x 3 + 1 = 13. 13 blir det nye frøet. Det neste tilfeldige tallet er 40, som er lik 13 x 3 + 1 = 40. På denne måten er de etterfølgende tilfeldige tallene 121 og 364.

Følgende kode illustrerer bruken av lineær_congruential_engine, med et frø på 2:

linear_congruential_engineLCE (2);
cout <cout <cout <cout <cout <cout <cout <cout <

Utgangen er:

7
22
67
202
607
0
999

Det maksimale tilfeldige antallet håpet på her er 1000. Min for denne ordningen er fremdeles 0, og Max er nå 999, og disse kan brukes til å konvertere et tall som returneres til mellom 0 og 1 - se nedenfor

Det første tilfeldige tallet som er returnert er 7. Det er lik 2 x 3 + 1 = 7. 7 blir det nye frøet. Neste tilfeldige tall er 22, som er lik 7 x 3 + 1 = 22. 22 blir det nye frøet. Det neste tilfeldige tallet er 67, som er lik 22 x 3 + 1 = 67. På denne måten er de etterfølgende tilfeldige tallene 202 og 607.

Følgende kode bruker formelen ovenfor for å produsere et tilfeldig tall mellom 0 og 1, for denne motoren:

linear_congruential_engineLCE (2);
usignert int num = lce (); // Normalt tilfeldig tall
usignert int min = LCE.min ();
usignert int max = LCE.maks ();
float random_number = ((float) (num - min))/((float) (maks - min));
cout <

Utgangen er:

0.00700701

Her er NUM 7, og så

random_number = (7 - 0)/(999 - 0) = 7/999 = 0.00700701 avrundet til 8 desimaler.

linear_congruential_engine er ikke den eneste spesialiserte motoren i det tilfeldige biblioteket; Det er andre.

standard_random_engine

Dette er som en generell motor. Det produserer tilfeldige tall. Sekvensrekkefølgen er ikke garantert å være ikke bestemt. Bestillingen er imidlertid sannsynligvis ikke kjent av programmereren. Følgende to linjer viser hvordan denne motoren kan brukes:

random_device rd;
standard_random_engine eng (rd ());

random_device er en klasse som RD er blitt instantiert. Legg merke til parentesene for RD i argumentlistene til motoren. En distributør trenger denne motoren for sin drift - se nedenfor.

Tilfeldige tallfordelingsklasser
uniform_int_distribution

uniform_int_distribution
Sannsynligheten for at et hvilket som helst antall vil oppstå er 1 delt på det totale antallet tall for denne klassen. For eksempel, hvis det er ti mulige utgangsnumre, er sannsynligheten for at hvert nummer vises 1/10. Følgende kode illustrerer dette:

random_device rd;
standard_random_engine eng (rd ());
uniform_int_distributionDist (3, 12);
cout <cout <

Utgangen fra forfatterens datamaskin er:

9 8 3 5 12
7 4 11 7 6

Dessverre har 7 dukket opp to ganger på bekostning av 10. Argumentene til Dist er tallene 3 og 13 inkluderende (ti heltall). Dist (Eng) er en operatør som returnerer neste nummer. Den bruker motoren. Legg merke til bruken av INT -malspesialiseringen.

Det er ikke nødvendig å se etter Num, Min og Max for denne saken og deretter bruke formelen ovenfor for å få et tall mellom 0 og 1. Dette er fordi det er en floatekvivalent av denne klassen som bruker float -spesialisering. Utgangen vil ikke være den samme for hver kjøring.

uniform_real_distribution

uniform_real_distribution ligner på uniform_int_distribution. Med det, for å få et tall mellom 0 og 1, bare bruk 0 og 1 som argumenter. Følgende kode illustrerer dette:

random_device rd;
standard_random_engine eng (rd ());
uniform_real_distributiondist (0, 1);
cout <cout <

Utgangen fra forfatterens datamaskin er:

0.384051 0.745187 0.364855 0.122008 0.580874
0.745765 0.0737481 0.48356 0.184848 0.745821

Legg merke til bruken av flytemalspesialisering. Utgangen vil ikke være den samme for hver kjøring.

binomial_distribution

Med denne distribusjonen er sannsynligheten for hvert utgangsnummer ikke den samme. binomial_distribution er illustrert ovenfor. Følgende kode viser hvordan du bruker binomial_distribution for å produsere 10 tilfeldige tall:

random_device rd;
standard_random_engine eng (rd ());
binomial_distributiondist (10);
cout <cout <

Utgangen fra forfatterens datamaskin er:

5 3 5 5 7
6 6 5 8 3

Utgangen vil ikke være den samme for hver kjøring. Malspesialiseringen som brukes her er int.

Følgende kode bruker formelen ovenfor for å produsere et tilfeldig tall mellom 0 og 1, for denne distribusjonen:

random_device rd;
standard_random_engine eng (rd ());
binomial_distributiondist (10);
usignert int num = dist (Eng); // Normalt tilfeldig tall
usignert int min = dist.min ();
usignert int max = dist.maks ();
cout <cout <cout <cout <float random_number = ((float) (num - min))/((float) (maks - min));
cout <

Utgangen fra forfatterens datamaskin er:

0
10
7
0.7

Bedre tilfeldig tall

Antall sekunder siden UNIX -epoken kan brukes som frø. Det blir vanskelig for hackeren å kjenne frøet. Følgende program illustrerer dette med linear_congruential_engine:

#inkludere
#inkludere
#inkludere
ved hjelp av navneområdet STD;
int main ()

const Auto P1 = Chrono :: System_Clock :: Now ();
usignert int frø = chrono :: varighet_cast(P1.time_since_epoch ()).telle();
linear_congruential_engineLCE (frø);
cout <cout <cout <cout <retur 0;

Utgangen fra forfatterens datamaskin er:

91 274 823 470 411
0
999

Merk at Chrono -biblioteket er inkludert. Utgangen er forskjellig for hver kjøring.

Konklusjon

Den enkleste måten å ha et tilfeldig tall mellom 0 og 1 er å bruke random_device, standard_random_engine og uniform_real_distribution (med argumenter 0 og 1). Enhver annen motor eller distribusjon som brukes kan trenge formelen, random_number = (num - min)/(maks - min).