Funkcia náhodného C ++

V stredu vytváranie STL a násilnou vojnu za štandardný jazyk C ++ niekoľko programátori Vyvinuli sme vlastnú krossplatformennuyu triedna knižnica, ktorá poskytuje vývojárom nástroje pre každodenné úlohy, ako je spracovanie dát algoritmy, práca so súbormi a tak ďalej. D. Táto knižnica sa nazýva basov , Projekt je taký úspešný, že schopnosti spoločnosti Boost sa vypožičiavajú a zapadajú do štandardného jazyka, počnúc C ++ 11. Jednou z takýchto aplikácií je vylepšená práca s náhodnými číslami.


Funkcie rand () a srand () sa týkajú úrovne školy a sú vhodné na písanie jednoduchých programov. Mínus týchto funkcií je generovanie nedostatočne dobrých sekvencií pseudonáhodných čísel (pozri vyššie). Tiež vlastnosti jednoduchých funkcií nestačia na vývoj komplexných projektov. Generátory náhodných čísel (ďalej len "MHF") boli vynájdené na riešenie vznikajúceho problému. S príchodom výrazne zlepšila práca generovať viac dát ako pseudo a pravda náhodná. Príkladom generovania skutočne náhodných čísel je hluk na obrázku nižšie.

Generátor pseudonáhodných čísel

Tradičné algoritmus pre vytváranie stredy kombinuje algoritmus pre vytváranie nepredvídateľné bitov a prevádza ich na sekvenciu čísel. V náhodnej C ++ knižnici, ktorá je súčasťou Boostu, rozdelili tieto dva mechanizmy. Teraz generovanie náhodných čísel a ich vytvorenie distribúcie (sekvenovanie) nastane samostatne. Použitie distribúcie je absolútne logické. Pretože náhodné číslobez konkrétneho kontextu nemá zmysel a je ťažké ho použiť. Sme napísať jednoduchú funkciu, ktorý vyvolá kosti:




# include
int roll_a_dice () {
std :: default_random_engine e {}; //vytvorí náhodný generátor
, std :: uniform_int_distribution d {júna 1} //vytvorí rozdelenie s minimálne a maximálne hodnoty
vratného d (e);
}

Bežnou chybou učiaci náhodné, je ignorovať tvorbu a distribúciu prechodu okamžite vytvoriť náhodných čísel spôsobom, na ktorý sú zvyknutí. Pozrime sa na túto funkciu.

návrat 1 + e ()% 6;

Niektorí veria, že jeho použitie je prípustné. Pretože C ++ vám to umožňuje. Tvorcovia knižnice Boost a štandardov C ++ 11 sa však dôrazne neodporúčajú. V najlepšom prípade to bude zlý tvar kódu, a v najhoršom prípade - nefunguje kód, ktorý má chyby, ktoré sú veľmi ťažké chytiť. Použitie distribúcie zabezpečuje, že programátor dostane to, čo sa očakáva.

Inicializácia generátora a osivo

Krok oznámenia, definície a tvorba subjektov je často vnímaná ako niečo, čo nestojí za pozornosť. Ale nedostatočne premyslené inicializovanie generátora náhodných čísel môže ovplyvniť jeho správnu prácu.

std :: default_random_engine e1; //implicitná inicializácia na predvolenú hodnotu
std :: default_random_engine e2 {}; //explicitná inicializácia štandardne

Prvé dve inicializácie sú ekvivalentné. A z väčšej časti sa týkajú chuti alebo štandardov písania dobrého kódu. Ďalšia inicializácia je však radikálna.


Ak je program spustený niekoľkokrát, generátor vždy generuje rovnakú sekvenciu čísel v prípade inicializácia nezmení Táto definícia generátor deje rovnakým spôsobom, od začiatku až do spustenia programu. Na jednej strane je taká samoreprodukcia čísel generátorom užitočná, napríklad pri ladení. Na druhej strane je to nežiaduce a môže spôsobiť problémy.

V súlade, aby sa zabránilo opakovaniu číslo sekvencie generátora inicializovaný má rôzne hodnoty pri každom spustení. Len na tieto účely môžete použiť osivo. Štandardná metóda inicializácia DPRCH je preniesť ju ako hodnota času semien

súbor hlavičky ctíme. To znamená, že generátor je inicializovaný hodnotousa rovná počtu sekúnd od 1. januára 00 hodín 00 minút 00 sekúnd, 1970 UTC.

Inicializácia DPRCH druhý generátor

, doba inicializácia nemusí byť dostatočne vyriešiť niektoré problémy. Potom môžete definovať DVR cez iný generátor. Tu by som chcel odbočiť a hovoriť o jednom mocný nástroj, ktorý vám umožní vytvoriť skutočne náhodných čísel.

Random_device - generátor náhodných čísel platí

Všetci generátori pseudonáhodných čísel sú deterministickí. To znamená, že majú definíciu. Alebo inými slovami, generovanie náhodných čísel je založené na matematických algoritmoch. Random_device je nedeterministická. Vytvára čísla založené na stochastických (náhodných z iných gréckych) procesov. Tieto procesy môžu zmeniť fázy alebo amplitúdy prúdu kolísanie molekulárnych poľa, pohyb vzduchových hmôt v atmosfére, a tak ďalej D.


. & Lt; script type = "text /javascript" & gt;
var blockSettings3 = {blockId: "R-A-70350-3", renderTo "yandex_rtb_R-A-70350-3", async:! 0};

, ak (document.cookie.indexOf ("abmatch =") väčšie alebo rovné 0) {
blockSettings3 = {blockId: "RA-70350-3", renderTo "yandex_rtb_R-A-70350- 3 ", stav: 70350async: 0};
}

! Funkcie (a, b, c, d, e) {a [c] = a [c] || [], sa [C] .push (funkcia () {Ya .Context.AdvManager.render (blockSettings3)}), e = b.getElementsByTagName ("scenár") , d = b.createElement ("scenár"), d.type = "text /javascript", d.src = "//an.yandex.ru/system/context.js",d.async=!0e.parentNode.insertBefore(d,e)}(this,this.document,"yandexContextAsyncCallbacks");

Je zrejmé, že nie každý počítač a nie každý systém môže byť zabudovaný do možnosti získať náhodné číslo založené na stochastickom procese. Preto je použitie náhodných funkcií v prípade potreby cenné. Jeho práca môžesa líšia od systému po systém, od počítača po počítač a možno sú úplne mimo dosahu. Pri používaní generátora skutočne náhodných čísel je preto potrebné zabezpečiť spracovanie chýb.

Použitie random_device ako osiva DPRCH

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

V tomto kóde nie je nič zásadne nové. Súčasne s každým spustením sa DIRF inicializuje náhodnými hodnotami generovanými generátorom skutočných náhodných čísel rd.

Treba tiež poznamenať, že inicializačný hodnota generátora môže byť kedykoľvek vynulované

e.seed (15027); //inicializujte podľa čísla
e.seed (); //inicializujte na predvolenú hodnotu
e.seed (rd ()); //inicializovať ďalšie generátor

zovšeobecniť generátory a distribúciu

generátora (motora) - objekt, ktorý umožňuje vytvoriť rôzne rovnako pravdepodobné čísla.

priemer (distirbution) - objekt, ktorý prevádza postupnosť čísel vytvorených generátorom, distribúcia určitého práva, ako v

  • jednotné (jednotné);
  • normálna - Gaussova distribúcia (normálna);
  • binomický (binom) atď.

Zvážte generátory štandardnej knižnice C ++.

  1. Nestačí, aby nováčikov používal default_random_engine a ponechal výber generátora do knižnice. Generátor sa vyberie na základe kombinácie faktorov, ako je výkon, veľkosť, kvalita náhody.
  2. Pre pokročilých používateľov poskytuje knižnica 9 predkonfigurovaných generátorov. Od seba sú veľmi odlišnéproduktivitu a veľkosť, ale ich kvalita práce bola zároveň predmetom serióznych testov. Často sa často používa oscilátor nazývaný motory Mersenne twister a jeho inštancia mt19937 (vytvorenie 32-bitových čísel) a mt19937_64 (vytvorenie 64-bitových čísel). Generátor je optimálna kombinácia rýchlosti a stupňa náhodnosti. Pre väčšinu problémov to bude stačiť.
  3. Knižnica poskytuje odborníkom nakonfigurované šablóny pre generátory, ktoré umožňujú vytvorenie ďalších typov generátorov.

Zvážte kľúčové aspekty rozdelenia. V štandarde svojho jazyka je 20 kusov. Vo vyššie uvedenom príklade bola jednotná distribúcia náhodnej C ++ knižnice v rozsahu [a, b] pre celé čísla použitá jednotná_rozdeľovanie. Táto distribúcia môže byť použitá pre reálne čísla: rovnomerné rozdelenie s rovnakými parametrami a a b ako generovanie čísel. Súčasne sú zahrnuté hranice medzery, tj [a, b]. Zoznam všetkých 20 distribúcií a opakovanie C ++ dokumentácie v článku nemá zmysel.

Treba poznamenať, že každé rozdelenie zodpovedá jeho súboru parametrov. Pre rovnomerné rozdelenie je to interval od a do b. A pre geometrický parameter (geometric_distribution) existuje pravdepodobnosť úspechu p.

Väčšina distribúcií je definovaná ako šablóna triedy, pre ktorú je parametrom typ hodnôt sekvencií. Niektoré distribúcie však vytvárajú sekvencie len hodnoty int alebo iba reálnej hodnoty. Napríklad Bernoulliho sekvencia (bernoulli_distribution) udáva hodnotu typu bool. Rovnako ako MHF, môže používateľ knižnicevytvorte si vlastnú distribúciu a použitie s vloženými generátormi alebo generátormi, ktoré vytvoria.

V tejto funkcii nie sú knižnice obmedzené. Sú oveľa širšie. Poskytnuté informácie však stačia na použitie a základné pochopenie generátora náhodných čísel v jazyku C ++.

pozadia: Náhodný štýl Net

Rámec NET je tiež prítomný Random trieda na generovanie náhodných čísel. Pozrime sa na príklad generovania náhodného čísla C ++ /CLI.

Pre tých, ktorí pracujú v Visual Studio a nemôžu pochopiť, prečo nie je definovaný názvový priestor systému.

Pre prácu .net je potrebné pripojiť CLR. To sa vykonáva v dvoch sposobamy.1) Vytvorenie projektu nie je windows konzolová aplikácie, a podporuje CLR - konzolová aplikácia CLR (CLR aplikácia konzoly) .2) podporu Connect CLR pri stanovovaní existujúci projekt: Vlastnosti projektu (v rámci "projektu", a nie " služba ") - & gt; konfigurácia - & gt; všeobecné - & gt; predvolená hodnota - & gt; drop-down list na "podporu Common Language Runtime (CLR)" zvoľte "CLR-environmentálna pomoc (/CLR)".

#include "stdafx.h"
#include

//using namespace System;

int main (array ^ args)
{
systému :: Náhodné ^ RND1 = gcnew System :: Náhodné (); //vytvorí generátor náhodných čísel, v predvolenom, aktuálny čas je inicializovaný
std :: cout rnd1- & gt; ďalší (), "n"; //vráti kladné celé číslo

int horné = 50;
std :: cout rnd1- & Next (horná) "n"; //vráti kladné celé číslo nie viac ako horné

int a = -1000; int b = -500;
std :: cout rnd1- & Next (a, b) "n"; //vracia celé číslo v rozsahu [a, b]

int seed = 13977;
Systém :: Náhodné ^ rnd2 = gcnew Systém :: Náhodné (osivo); //inicializujte MHFpočet semien
std :: cout rnd2- & Next (5001000) n; //pri každom spustení programu sa vytvorí rovnaké číslo.

std :: cout std :: endl;

návrat 0;
}

V tomto prípade sa všetka práca vykonáva pomocou funkcie Random Next C ++ /CLI.

Treba poznamenať, že .net je veľká knižnica s veľkými možnosťami a používa vlastnú verziu jazyka C ++ /CLI z Common Language Infrastructure. Vo všeobecnosti ide o rozšírenie C ++ na platformu .Net.

Na záver uvažujme niekoľko príkladov, aby sme lepšie pochopili prácu s náhodnými číslami.#include
#include
#include
std :: mt19937 e1;
e1.seed (čas

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

std :: mt19937 e2 (čas

);

std :: mt19937 e3 {};
std :: jednotná_roznášacia 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); //normálna distribúcia s priemernou hodnotou 5,0 a stredná štvorcová odchýlka 2,0
std :: cout urd (e4), nd (e4) std :: endl;

std :: cout std :: endl;
("pauza");
návrat 0;
}

Záver

Všetky technológie a metódy sa neustále vyvíjajú a rafinujú. To sa stalo aj s mechanizmom generovania náhodných čísel rand (), ktorý je zastaralý a prestal spĺňať moderné požiadavky. V STL existuje náhodná knižnica, v rámci .Net Framework - náhodná trieda na prácu s náhodnými číslami. Použitie rand by malo odmietnuť výhody nových metód, pretože zodpovedajú moderným programovým paradigmom a staré metódy budú vyňaté z normy.

Súvisiace publikácie