Funcția C ++ aleatoriu

În mijlocul de a crea STL și război violent pentru numărul standard de limbajul C ++ de programatori au dezvoltat biblioteca noastră proprie de clasa cross-platform oferind dezvoltatorilor instrumentele necesare pentru a se ocupa de sarcinile de zi cu zi, cum ar fi procesarea de date, algoritmi, și de a lucra cu fișiere și așa mai departe. D. Această bibliotecă se numește Boost. Proiectul este atât de reușit încât capabilitățile Boost sunt împrumutate și se încadrează în standardul de limbă, începând cu C ++ 11. Una dintre aceste adăugiri este o lucrare îmbunătățită cu numere aleatorii.

Generator pseudo-aleator

Funcțiile rand () și srand () se referă la nivelul școlii și sunt potrivite pentru scrierea programelor simple. Dezavantajul acestor funcții este generarea unei succesiuni insuficiente de numere pseudo-aleatoare (imaginea de mai sus). De asemenea, posibilitățile funcțiilor simple nu sunt suficiente atunci când se dezvoltă proiecte complexe.

Pentru a rezolva problema, au fost inventați generatori de numere aleatorii (în continuare RNG). Odată cu apariția lor, activitatea de generare a mai multor tipuri de date, atât pseudo-cât și cu adevărat aleatoare, a fost îmbunătățită considerabil. Un exemplu de generare de numere cu adevărat aleatoare este zgomotul din imaginea de mai jos.

Chiar generator de aleatoare

Generator de numere pseudo-aleatoare

Diceul este un simbol al hazardului

Algoritmul tradițional pentru crearea MF combină atât algoritmul de creare a biților imprevizibili, cât și convertirea acestora într-o secvență de numere. În biblioteca C ++ aleatoare, care face parte din Boost, aceste două mecanisme sunt împărțite. Acum, generarea de numere aleatoare și crearea acestora (secvență) are loc separat. Utilizarea distribuției este complet logică. Deoarece un număr aleatoriu fără un anumit context nu are sens și este greu de folosit. Să scriem o funcție simplă care aruncă un os:

#include int roll_a_dice () {std :: default_random_engine e {} - // crea randomness generatorstd :: uniform_int_distribution	d {1, 6} // a crea o distribuție cu valorile min și max întoarce d (e) -}

O greșeală obișnuită pentru cei care studiază întâmplător este să ignorați crearea distribuției și să mergeți direct la crearea de numere aleatorii în modul în care sunt obișnuiți. De exemplu, luați în considerare funcția descrisă mai sus.

retur 1 + e ()% 6-

Unii consideră această utilizare acceptabilă. C ++ vă permite să lucrați în acest fel. Cu toate acestea, creatorii bibliotecii Boost și standardelor C ++ 11 sunt sfătuiți să nu facă acest lucru. În cel mai bun caz, va fi doar un cod rău, și în cel mai rău caz va fi un cod de lucru care face greșeli care sunt foarte greu de prins. Utilizarea distribuțiilor asigură că programatorul obține ceea ce așteaptă.

Generator și inițializare semințe

Stadiul de declarare, definire și crearea de entități este adesea văzut ca ceva care nu necesită o atenție deosebită. Dar inițializarea cu grijă a generatorului de numere aleatoare nu poate afecta buna funcționare a acestuia.

std :: default_random_engine E1- // Valoarea inițializarea implicită a umolchaniyustd :: default_random_engine e2 {} - // initializare explicită de valoarea implicită

Primele două inițializări sunt echivalente. Și în cea mai mare parte se referă la gust sau la standardele de scriere a unui cod frumos. Dar următoarea inițializare este radical diferită.

std :: default_random_engine e3 {31255} - // inițializare cu valoarea 31255

"31255" - se numește semințe (semințe, surse) - numărul pe baza căruia generatorul creează numere aleatorii. Punctul cheie aici este că, cu această inițializare, tipul de semințe ar trebui să fie același sau tipul cu care funcționează generatorul. Acest tip este accesibil prin construirea lui decltype (e ()), sau result_of, sau nume-tip.

De ce generatorul generează aceleași secvențe?

Când programul este rulat de mai multe ori, generatorul creează întotdeauna aceeași secvență de numere, dacă inițializarea acestuia nu se schimbă, adică definirea generatorului apare în același mod începând de la pornirea programului. Pe de o parte, această auto-reproducere a numerelor de către generator este utilă, de exemplu, atunci când se depanează. Și pe de altă parte - este nedorită și poate crea probleme.

În consecință, pentru a evita repetarea succesiunii de numere, generatorul trebuie inițializat cu valori diferite de fiecare dată când programul este pornit. Doar pentru aceste scopuri puteți folosi semințe. Modul standard de inițializare a GPRS este să-l trimiteți ca valoare de referință pentru semințe (0) din fișierul antetului ctime. Adică generatorul va fi inițializat cu o valoare egală cu numărul de secunde scurs de la 1 00 00 00 minute 00 secunde, 1970 de UTC.

Inițializarea GPRS cu alt generator

Inițializarea timpului poate să nu fie suficientă pentru a rezolva o serie de sarcini. Apoi, este posibil să se determine GPRS printr-un alt generator. Aici aș vrea să fac o digresiune și să vorbesc despre un instrument puternic care vă permite să creați numere cu adevărat aleatoare.

Random_device - generator de numere cu adevărat aleatoare

Numere aleatoare

Toate generatoarele de numere pseudo-aleatoare sunt deterministe. Asta înseamnă că ei au o definiție. Sau, cu alte cuvinte, primirea numerelor aleatoare se bazează pe algoritmi matematici. Dispozitivul Random este, de asemenea, nedeterminist. El creează numere pe baza proceselor stochastice (aleatorii cu greco-greacă). Astfel de procese pot fi schimbări în faza sau amplitudinea oscilațiilor curente, oscilațiilor în laturile moleculare, mișcarea masei de aer în atmosferă etc.

Evident, nu fiecare computer și fiecare sistem poate avea o capacitate încorporată de a obține un număr aleator pe baza unui proces stochastic. Prin urmare, ar trebui să recurgeți la utilizarea opțiunii random_device doar dacă este necesar. Lucrarea sa poate diferi de la sistem la sistem, de la calculator la calculator, și poate fi chiar inaccesibilă. Prin urmare, atunci când se utilizează un generator cu numere cu adevărat aleatoare, este necesar să se asigure manipularea erorilor.

Folosind funcția random_device ca semințe pentru RAND

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


Nu există nimic fundamental nou în acest cod. În același timp, cu fiecare lansare, GISCH este inițializat cu valori aleatorii generate de generatorul de numere cu adevărat aleatoare rd.

De asemenea, merită remarcat faptul că valoarea de inițializare a generatorului poate fi resetată în orice moment:

e.seed (15027) - chislome.seed // inițializarea () - // valoarea inițializarea umolchaniyue.seed (rd ()) - // inițializa un alt generator de

Generalități: generatoare și distribuții

Motorul este un obiect care vă permite să creați numere diferite echiprobabile.

Distribuția (distirbution) este un obiect care convertește secvența numerelor create de generator în distribuții conform unei anumite legi, de exemplu:

  • uniforma (uniform);
  • Normal - Gaussian (normal);
  • binomială și așa mai departe.

Luați în considerare generatorii bibliotecii standard C ++.

  1. Este suficient pentru începători să utilizeze default_random_engine, lăsând alegerea generatorului la bibliotecă. Generatorul va fi ales pe baza unei combinații de factori, cum ar fi performanța, dimensiunea, calitatea aleatorității.
  2. Pentru utilizatorii cu experiență, biblioteca oferă 9 generatoare presetate. Ele sunt foarte diferite unele de altele în dimensiune și performanță, dar în același timp, calitatea muncii a fost supus unor teste serioase. generator de motoare numit twister Mersenne și cazuri folosite adesea mt19937 (crearea unui număr de 32 de biți) și mt19937_64 (crearea de numere întregi pe 64 de biți). Generatorul este o combinație optimă de viteză și aleatorie. Pentru majoritatea problemelor care apar, va fi de ajuns.
  3. Pentru experți, biblioteca oferă șabloane configurabile de generatoare care permit crearea de tipuri suplimentare de generatoare.
Distribuția normală

Să luăm în considerare aspectele esențiale ale distribuțiilor. În limbajul standard există 20 dintre ele. În exemplul de mai sus, o distribuție aleatoare a librăriei C ++ aleatoare a fost utilizată în intervalul [a, b] pentru numere întregi - uniformă_distribuție. Aceeași distribuție poate fi utilizată pentru numere reale: repararea uniformă_reală cu aceiași parametri a și b ai intervalului de generare a numerelor. Mai mult decât atât, limitele intervalului sunt incluse, adică [a, b]. Enumerați toate cele 20 de distribuții și repetați documentația C ++ în articol nu are sens.

Trebuie remarcat faptul că fiecare distribuție are un set propriu de parametri. Pentru o distribuție uniformă, acesta este intervalul de la a la b. Și pentru un parametru geometric (geometric_distribution), probabilitatea succesului este p.

Cele mai multe distribuții sunt definite ca un șablon de clasă, pentru care parametrul este un tip de valori de secvență. Cu toate acestea, unele distribuții creează doar secvențe pentru valori int sau numai valori reale. Sau, de exemplu, secvența Bernoulli (bernoulli_distribution) care oferă valori precum bool. Ca și în cazul RNG, utilizatorul bibliotecii își poate crea propriile distribuții și le poate folosi cu generatoare încorporate sau cu generatoare care vor crea.

Distribuția gama

Capacitățile bibliotecii nu se limitează la aceasta. Ele sunt mult mai largi. Dar informațiile furnizate sunt suficiente pentru utilizarea și înțelegerea de bază a generatorului de numere aleatorii în C ++.

Informații scurte: Random în stilul .Net

Cadrul .Net are, de asemenea, o clasă aleatoare pentru crearea de numere pseudo-aleatoare. Să luăm în considerare un exemplu de generare Numărul aleatoriu Cu ++ / CLI.

Pentru cei care lucrează în Visual Studio și nu înțeleg de ce spațiul de nume al sistemului nu este definit.

Pentru a lucra cu .net, trebuie să conectați CLR-ul. Acest lucru se face în două sposobami.1) Crearea unui proiect nu este ferestre app consola, și cu sprijinul CLR - Console aplicație CLR (CRJ Console Application) .2) Conectați suportul CRJ în setările de proiect deja create: Proprietățile proiectului ( „Proiectul“, și nu " serviciu ") -> configurare -> General -> default -> în meniul drop-down caseta" suport pentru rulare limbaj comun (CLR) "selectați" Suport CLR-mediu (/ CLR)“.

#include "stdafx.h" #include // using namespace-System int main (matrice ^ args) {System :: Aleator ^ rnd1 = Sistem de gcnew :: Aleator () - // implicit crearea de RNG inițializat vremenemstd curente :: cout << rnd1-> Înainte () << " n" - // returnează un întreg pozitiv int superior = 50-std :: cout << rnd1-> Următorul (superior) << " n" - // returnează un întreg pozitiv nu mai mare decât upperint a = -1000- int b = -500-std :: cout << rnd1-> Înainte (a, b) << " N" - // returnează întreg în intervalul [a, b] sămânță int = 13977-System :: Aleator ^ rnd2 = Sistem gcnew :: random (semințe) - // inițializarea număr RNG seedstd :: cout << rnd2-> Înainte (500, 1000) << " n" - // de fiecare dată când programul este pornit, același număr va fi creat std :: cout << std :: endl-return 0-}

În acest caz, toată lucrarea se face grație funcției Random Next C ++ / CLI.

Este de remarcat faptul că .net este o bibliotecă vastă cu capacități extinse și utilizează propria versiune a limbajului, numită C ++ / CLI din Common Language Infrastructure. În general, aceasta este o extensie C ++ pentru platforma .Net.

Luați în considerare câteva exemple pentru a înțelege mai bine lucrul cu numere aleatorii.

#include #include #include int principal () {std :: mt19937 e1-e1.seed (timp (0)) - std :: cout << e1 () << std :: endl-std :: mt19937 e2 (time (0)) - std :: mt19937 e3 {} - std :: uniform_int_distribution uid1 (5, 10), uid2 (1, 6) -std :: cout << uid1 (e2) << "" << uid2 (e3) << std :: endl-std :: default_random_engine e4 {} - std :: uniform_real_distribution urd (0.5, 1.2) -std :: Distribuție normală nd (5.0, 2.0) - // distribuție normală cu o valoare medie de 5.0 și o abatere standard de 2.0std :: cout << urd (e4) << "" << nd (e4) << std :: endl-std :: cout << std :: endl-system ("pauză") - retur 0-}

concluzie

Orice tehnologie și metode sunt în continuă evoluție și îmbunătățire. Așa sa întâmplat cu mecanismul de generare a numerelor aleatoare rand (), care este depășit și a încetat să îndeplinească cerințele moderne. În STL, există o bibliotecă aleatoare, în cadrul .Net Framework, clasa Random pentru a lucra cu numere aleatorii. De la folosind rand Este necesar să se refuze în favoarea noilor metode, deoarece acestea corespund paradigmelor moderne de programare, iar metodele vechi vor fi derivate din standard.

Distribuiți pe rețelele sociale:

înrudit
Rotunjirea numerelor în programarea WEBRotunjirea numerelor în programarea WEB
Ce este o întâmplare? Vicisitudinile soarteiCe este o întâmplare? Vicisitudinile soartei
Random - ce este asta?Random - ce este asta?
Rand - ce este și ce mănâncă?Rand - ce este și ce mănâncă?
Ce este Ruby? Limba de programare "Ruby"Ce este Ruby? Limba de programare "Ruby"
Cele mai populare limbi de programare. Limbaje de programare pentru începătoriCele mai populare limbi de programare. Limbaje de programare pentru începători
Matematică din jаvascript MathMatematică din jаvascript Math
PHP: expresii regulate, funcția preg Match allPHP: expresii regulate, funcția preg Match all
Descriere: generator de numere de loterieDescriere: generator de numere de loterie
Limba de programare c (s)Limba de programare c (s)
» » Funcția C ++ aleatoriu