Slučajna C ++ funkcija

Na vrhuncu stvaranja STL-a i nasilnog rata standardnog jezika C ++, brojni programeri razvili su vlastitu knjižnicu višestrukih platformi koja nudi programerima alate za rješavanje svakodnevnih zadataka kao što su obrada podataka, algoritmi, manipulacija datotekama itd. , Projekt je tako uspješan da su mogućnosti Boost posuđene i uklapaju se u standardni jezik, počevši od C ++ 11. Jedna takva aplikacija je poboljšan rad sa slučajnim brojevima.


Funkcije rand () i srand () odnose se na razinu škole i prikladne su za pisanje jednostavnih programa. Minus tih funkcija je generiranje nedovoljno dobrog niza pseudoslučajnih brojeva (vidi gore). Također, značajke jednostavnih funkcija nisu dovoljne za razvoj složenih projekata. Generatori slučajnih brojeva (u daljnjem tekstu MHF) izumljeni su kako bi se riješio nastali problem. Svojim izgledom, rad na generiranju više vrsta podataka, kako pseudo-i istinski slučajnih, značajno se poboljšao. Primjer stvaranja slučajnih brojeva je buka na slici ispod.

Generator pseudoslučajnih brojeva

Tradicionalni algoritam za stvaranje MF kombinira i algoritam stvaranja nepredvidivih bitova i njihovo pretvaranje u niz brojeva. U nasumičnoj C ++ knjižnici, koja je dio Boost-a, razdvajaju ova dva mehanizma. Sada se generiranje slučajnih brojeva i njihovo stvaranje distribucije (sekvenciranje) odvija odvojeno. Korištenje distribucije je apsolutno logično. Zbog slučajnog brojabez određenog konteksta, nema smisla i teško ga je koristiti. Napiši jednostavnu funkciju koja baca kost:




# uključi
int roll_a_dice () {
std :: default_random_engine e {}; //stvoriti slučajni generator
std :: uniform_int_distribution d {1 6} //stvoriti distribuciju mina i max vrijednosti
povratak d (e);
}

Tipična pogreška onih koji proučavaju nasumično jest ignorirati stvaranje distribucije i prijelaz na stvaranje slučajnih brojeva na način na koji su navikli. Na primjer, pogledajmo ovu značajku.

povratak 1 + e ()% 6;

Neki smatraju da je njegova uporaba dopuštena. Zato što vam C ++ to omogućuje. Međutim, kreatorima knjižnice Boost i C ++ 11 preporuča se da to ne čine. U najboljem slučaju, to će jednostavno biti loš kod, au najgorem slučaju to će biti trčanje kod koji pravi pogreške koje je vrlo teško uhvatiti. Korištenje distribucija osigurava da programer prima ono što se očekuje.

Inicijalizacija generatora i sjemena

Stupanj objavljivanja, definiranja i stvaranja entiteta često se smatra nečim što nije vrijedno posebne pozornosti. No, nedovoljno promišljena inicijalizacija generatora slučajnih brojeva može utjecati na njegov ispravan rad.

std :: default_random_engine e1; //implicitna inicijalizacija na zadanu vrijednost
std :: default_random_engine e2 {}; //eksplicitna inicijalizacija po defaultu

Prve 2 inicijalizacije su ekvivalentne. Većinom se odnose na okus ili standarde pisanja dobrog koda. Ali sljedeća inicijalizacija je radikalno drugačija.


& lt; script type = "text /javascript" & gt;
može blockSettings2 = {blockId: "R-A-70350-2", renderTo: "yandex_rtb_R-A-70350-2", async:! 0};

if (document.cookie.indexOf ("abmatch =") & gt; = 0) {
blockSettings2 = {blockId: "RA-70350-2", renderTo: "yandex_rtb_R-A-70350- 2 ", statId: 70350async: 0};
}

Funkcija (a, b, c, d, e) {a [c] = a [c] || [], a [c] .push (funkcija () {Ya .Context.AdvManager.render (blockSettings2)}), e = b.getElementsByTagName ("script") , d = b.createElement ("script"), d.type = "text /javascript", d.src = "//an.yandex.ru/system/context.js", d.async =! 0e.parentNode.insertBefore (d, e)} (ovaj, ovaj.dokument, "yandexContextAsyncCallbacks");
std :: default_random_engine e3 {31255}; //inicijalizirati na 31255

"31255" - to se naziva sjeme (sjeme, izvor) - broj na temelju kojeg generator stvara slučajne brojeve. Ključna točka ovdje je da s takvom inicijalizacijom, vrsta sjemena treba biti ista ili se odnosi na tip s kojim generator radi. Ovaj tip je dostupan putem decltype (e ()), ili result_of, ili typename konstrukta.

Zašto generator stvara identične sekvence?

Kada se program pokreće nekoliko puta, generator uvijek stvara isti niz brojeva ako se njegova inicijalizacija ne mijenja, tj. Definicija generatora je na isti način od početka do pokretanja programa. S jedne strane, takva samoreprodukcija brojeva od strane generatora korisna je, na primjer, pri otklanjanju pogrešaka. S druge strane, to je nepoželjno i može stvoriti probleme. Prema tome, kako bi se izbjeglo ponavljanje niza brojeva, generator mora inicijalizirati različite vrijednosti pri svakom pokretanju programa. Samo za te svrhe možete koristiti sjeme. Standardni način inicijalizacije DWR-a je slanje vrijednosti sjeme vremena

datoteke ctime zaglavlja. To jest, generator se inicijalizira po vrijednostijednako broju sekundi od siječnja 1 00 sati 00 minuta 00 sekundi, 1970 UTC.

Inicijaliziranje DVR-a od strane drugog generatora

Vrijeme inicijalizacije možda neće biti dovoljno za rješavanje niza problema. Tada možete definirati DVR putem drugog generatora. Ovdje bih želio napraviti povlačenje i razgovarati o jednom moćnom alatu koji vam omogućuje stvaranje istinski slučajnih brojeva.

Random_device - Generator pravih slučajnih brojeva

Svi generatori pseudoslučajnih brojeva su deterministički. To jest, oni imaju definiciju. Drugim riječima, generiranje slučajnih brojeva temelji se na matematičkim algoritmima. Random_device nije nedefiniran. Stvara brojeve na temelju stohastičkih (nasumičnih iz drugih grčkih) procesa. Takvi procesi mogu biti promjene faze ili amplitude strujnih fluktuacija, fluktuacije molekularnih rešetki, kretanje zračnih masa u atmosferi, itd.


& lt; script type = "text /javascript" & gt;
može blockSettings3 = {blockId: "R-A-70350-3", renderTo: "yandex_rtb_R-A-70350-3", async: 0};

if (document.cookie.indexOf ("abmatch =") & gt; = 0) {
blockSettings3 = {blockId: "RA-70350-3", renderTo: "yandex_rtb_R-A-70350- 3 ", statId: 70350sync:! 0};
}

Funkcija (a, b, c, d, e) {a [c] = a [c] || [], a [c] .push (funkcija () {Ya .Context.AdvManager.render (blockSettings3)}), e = b.getElementsByTagName ("script") , d = b.createElement ("script"), d.type = "text /javascript", d.src = "//an.yandex.ru/system/context.js", d.async =! 0e.parentNode.insertBefore (d, e)} (ovaj, ovaj.dokument, "yandexContextAsyncCallbacks");

Očito je da se ne može svako računalo, a ne svaki sustav, ugraditi u mogućnost dobivanja slučajnog broja na temelju stohastičkog procesa. Stoga, korištenje random_device vrijedi samo ako je potrebno. Njegov rad možerazlikuju se od sustava do sustava, od računala do računala, a možda je i izvan dosega. Stoga, kada se koristi pravi generator slučajnih brojeva, potrebno je omogućiti rukovanje pogreškama.

Korištenje random_device kao sjeme za DSPF

std :: random_device rd {};
std :: default_random_engine e {rd ()};

U ovom kodeksu ne postoji ništa bitno novo. U isto vrijeme, sa svakim startom, DIRF se inicijalizira slučajnim vrijednostima koje generira pravi generator slučajnih brojeva rd.

Također je vrijedno spomenuti da se inicijalna vrijednost generatora može resetirati u bilo kojem trenutku:

e. Seed (15027); //inicijalizira se brojem
e.seed (); //inicijalizirati na zadanu vrijednost
e.seed (rd ()); //Inicijalizacija s drugim generatorom

Sažemo: generatori i distribucije

Generator (motor) je objekt koji omogućuje stvaranje različitih brojeva vjerojatnosti.

Distirbution je objekt koji pretvara niz brojeva generiranih od generatora u distribuciju prema određenom zakonu, na primjer:

  • uniformu (uniformu);
  • normalna - Gaussova distribucija (normalna);
  • binomni (binom), itd.

Razmotrimo generatore standardne C ++ biblioteke.

  1. Dovoljno je da početnici koriste default_random_engine, ostavljajući odabir generatora u knjižnici. Generator će biti odabran na temelju kombinacije čimbenika kao što su izvedba, veličina, kvaliteta slučajnosti.
  2. Knjižnica za napredne korisnike nudi 9 unaprijed konfiguriranih generatora. Vrlo se razlikujuproduktivnost i veličina, ali u isto vrijeme, njihova kvaliteta rada bila je podvrgnuta ozbiljnim testovima. Često se koristi oscilator nazvan Mersenne twister engine i njegov primjer mt19937 (stvaranje 32-bitnih brojeva) i mt19937_64 (stvaranje 64-bitnih brojeva). Generator je optimalna kombinacija brzine i stupnja slučajnosti. Za većinu izazova to će biti dovoljno.
  3. Za stručnjake, knjižnica pruža konfigurirane predloške za generatore koji omogućuju stvaranje dodatnih vrsta generatora.

Razmotrite ključne aspekte raspodjele. U standardu njihovog jezika postoji 20 komada. U gornjem primjeru korištena je ravnomjerna raspodjela nasumične C ++ biblioteke u rasponu [a, b] za cijele brojeve uniform_int_distribution. Ova distribucija se može koristiti za realne brojeve: uniform_real_distribution s istim parametrima a i b kao generiranje brojeva. Istovremeno su uključene i granice jaza, tj. [A, b]. Navedite svih 20 distribucija i ponovite C ++ dokumentaciju u članku nema smisla.

Treba napomenuti da svaka distribucija odgovara njezinom skupu parametara. Za ravnomjernu raspodjelu to je interval od a do b. A za geometrijski parametar (geometric_distribution) postoji vjerojatnost uspjeha p.

Većina distribucija definirana je kao predložak klase, za koji je parametar vrsta slijednih vrijednosti. Međutim, neke distribucije stvaraju sekvence samo int vrijednosti ili samo stvarnu vrijednost. Ili, na primjer, Bernoullijeva sekvenca (bernoulli_distribution) daje vrijednost tipa bool. Kao i kod MHF-a, korisnik knjižnice možestvorite vlastitu distribuciju i koristite s ugrađenim generatorima ili generatorima koji će stvoriti.

U tom svojstvu knjižnice nisu ograničene. Oni su mnogo širi. Ali pružene informacije su dovoljne za korištenje i osnovno razumijevanje generatora slučajnih brojeva u C ++.

Kratka pomoć: Slučajna u .Net stilu

.Net okvir također uključuje Random klasu za stvaranje pseudoslučajnih brojeva. Razmotrimo primjer generiranja slučajnog broja C ++ /CLI.

Za one koji rade u Visual Studiou i ne mogu razumjeti zašto prostor imena sustava nije definiran.

Za rad .net potrebno je povezati CLR. To se radi na dva načina: 1) Stvaranje projekta nije Windows konzolna aplikacija, nego CLR - CLR aplikacije (CLR Console Application) 2) Povezivanje CLR podrške u postavkama već kreiranog projekta: svojstva projekta (kartica projekta, ne usluga ") - & gt; konfiguracija - & gt; općenito - & gt; zadana vrijednost - & gt; u padajućem okviru "Podrška za opću runtime okruženje (CLR)" odaberite "CLR podrška za okoliš (/clr)".

# uključiti "stdafx.h"
# uključiti

//koristiti imenski sustav;

int main (polje ^ args)
{
Sustav :: Random ^ rnd1 = gcnew sustav :: Random (); //kreiramo MHF, po defaultu se inicijalizira trenutnim vremenom
std :: cout rnd1- & gt; Next () "n"; //vraća pozitivan cijeli broj

int upper = 50;
std :: cout rnd1- & gt; Sljedeći (gornji) "n"; //vraća pozitivan cijeli broj ne veći od gornjeg

int a = -1000; int b = -500;
std :: cout rnd1- & gt; Dalje (a, b) "n"; //vraća cijeli broj u rasponu [a, b]

int seed = 13977;
Sustav :: Slučajni ^ rnd2 = gcnew sustav :: Random (sjeme); //inicijalizirati MHFbroj sjemena
std :: cout rnd2 -> Sljedeći (5001000) n; //isti broj će biti kreiran pri svakom pokretanju programa.

std :: cout std :: endl;

povratak 0;
}

U ovom slučaju, sav se posao obavlja funkcijom Random Next C ++ /CLI.

Važno je napomenuti da je .net velika knjižnica s velikim mogućnostima i koristi vlastitu verziju jezika zvanog C ++ /CLI iz zajedničke jezične infrastrukture. Općenito, ovo je proširenje C ++ na .Net platformu.

Razmotrimo na kraju nekoliko primjera kako bismo bolje razumjeli rad s slučajnim brojevima.# uključiti
# uključiti
# uključiti
int main () {
std :: mt19937 e1;
e1.seed (vrijeme

);
std :: cout e1 () std :: endl;

std :: mt19937 e2 (vrijeme

);

std :: mt19937 e3 {};
std :: uniform_int_distribution uid1 (510), uid2
;
std :: cout uid1 (e2) "," uid2 (e3) std :: endl;

std :: default_random_engine e4 {};
std :: uniform_real_distribution urd (051.2);
std :: normal_distribution nd (502.0); //normalna distribucija s prosječnom vrijednošću 5,0 i srednjom kvadratnom devijacijom 2,0
std :: cout urd (e4) "," nd (e4) std :: endl;

std :: cout std :: endl;
sustav ("pauza");
povratak 0;
}


Zaključak

Sve tehnologije i metode stalno se razvijaju i usavršavaju. To se također dogodilo s mehanizmom generiranja slučajnih brojeva rand (), koji je zastario i prestao je zadovoljavati suvremene zahtjeve. U STL-u postoji slučajna knjižnica, u .Net Framework-u - Random klasa za rad sa slučajnim brojevima. Upotreba randa trebala bi odbiti prednosti novih metoda, jer one odgovaraju suvremenim programskim paradigmama, a stare metode će biti isključene iz standarda.

Povezane publikacije