Funkce náhodného C ++

Ve středu vytváření STL a násilnou válku za standardní jazyk C ++ několik programátoři Vyvinuli jsme vlastní krossplatformennuyu třídní knihovna, která poskytuje vývojářům nástroje pro každodenní úkoly, jako je zpracování dat algoritmy, práce se soubory a tak dále. D. Tato knihovna se nazývá basů . Projekt je tak úspěšný, že funkce Boostu jsou vypůjčeny a zapadají do standardního jazyka, počínaje C ++ 11. Jednou z takových aplikací je zdokonalená práce s náhodnými čísly.


Funkce rand () a srand () se vztahují k úrovni školy a jsou vhodné pro psaní jednoduchých programů. Mnohem z těchto funkcí je generování nedostatečně dobré posloupnosti pseudonáhodných čísel (viz výše). Také funkce jednoduchých funkcí nestačí k tomu, aby vyvíjely složité projekty. Generátory náhodných čísel (dále jen "MHF") byly vynalezeny k vyřešení vznikajícího problému. S jejich vzhledu se práce na generování mnoha typů dat, jak pseudo-tak opravdu náhodných, výrazně zlepšila. Příkladem generování skutečně náhodných čísel je šum na obrázku níže.

Generátor pseudonáhodných čísel

Tradiční algoritmus pro vytváření středy kombinuje algoritmus pro vytváření nepředvídatelné bitů a převádí je na sekvenci čísel. V náhodném C ++ knihovně, která je součástí Boost, rozdělila tyto dva mechanismy. Nyní se vytváří náhodná čísla a vytváření jejich distribuce (sekvence) samostatně. Použití distribuce je naprosto logické. Protože náhodné číslobez zvláštního kontextu nemá smysl a je obtížné ho používat. Jsme napsat jednoduchou funkci, který vyvolá kosti:




# include
int roll_a_dice () {
std :: default_random_engine e {}; //vytvoří náhodný generátor
, std :: uniform_int_distribution d {června 1} //vytvoří rozdělení s minimální a maximální hodnoty
vratného d (e);
}

Běžnou chybou učící náhodné, je ignorovat tvorbu a distribuci přechodu okamžitě vytvořit náhodných čísel způsobem, na který jsou zvyklí. Podívejme se například na tuto funkci.

návrat 1 + e ()% 6;

Někteří věří, že jeho použití je přípustné. Protože C ++ vám to umožňuje. Tvůrcům knihovny Boost a standardům C ++ 11 se však doporučuje, aby tak neučinily. V nejlepším případě to bude špatný tvar kódu, a v nejhorším případě - nefunguje kód, který má chyby, které jsou velmi těžké chytit. Použití distribucí zajišťuje, že programátor obdrží to, co se očekává.

Inicializace generátoru a osivo

Krok oznámení, definice a tvorba subjektů je často vnímána jako něco, co nestojí za pozornost. Ale nedostatečně promyšlená inicializace generátoru náhodných čísel může ovlivnit jeho správnou práci.

std :: default_random_engine e1; implicitní inicializace na výchozí hodnotu
std :: default_random_engine e2 {}; //explicitní inicializace ve výchozím nastavení

První dvě inicializace jsou ekvivalentní. A z větší části se týkají chuti nebo standardů psaní dobrého kódu. Další inicializace je však radikálně odlišná.


Je-li program spuštěn několikrát, generátor vždy generuje stejnou sekvenci čísel v případě inicializace nezmění Tato definice generátor děje stejným způsobem, od začátku až do spuštění programu. Na jedné straně je taková samoreprodukce čísel generátorem užitečná, například při ladění. Na druhou stranu je to nežádoucí a může způsobit problémy.

V souladu, aby se zabránilo opakování číslo sekvence generátoru inicializován má různé hodnoty při každém spuštění. Jen pro tyto účely můžete použít osivo. Standardním způsobem, jak inicializovat DWR, je odeslat počáteční hodnotu času

souboru šablony záhlaví. To znamená, že generátor je inicializován hodnotouse rovná počtu sekund od 1. ledna 00 hodin 00 minut 00 sekund, 1970 UTC.

Inicializace DPRCH druhý generátor

, doba inicializace nemusí být dostatečně vyřešit některé problémy. Pak můžete DVR definovat jiným generátorem. Zde bych chtěl odbočit a mluvit o jednom mocný nástroj, který vám umožní vytvořit skutečně náhodných čísel.

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

generátor pseudonáhodných čísel je určen. To znamená, že mají definici. Jinými slovy, generování náhodných čísel je založeno na matematických algoritmech. Random_device je nedeterministická. Vytváří čísla založená na stochastických (náhodných z jiných řeckých) procesů. Tyto procesy mohou změnit fáze nebo amplitudy proudu kolísání molekulárních pole, pohyb vzduchových hmot v atmosféře, a tak dále D.


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

, pokud (document.cookie.indexOf ("abmatch =") větší nebo rovno 0) {
blockSettings3 = {blockId: "RA-70350-3", renderTo „yandex_rtb_R-A-70350- 3 ", statId: 70350async:! 0};
}

! Funkce (a, b, c, d, e) {a [c] = a [c] || [], se [C] .push (funkce () {Ya .Context.AdvManager.render (blockSettings3)}), e = b.getElementsByTagName ("scénář") , d = b.createElement ("scénář"), d.type = "text /javascript", d.src = "//an.yandex.ru/system/context.js",d.async=!0e.parentNode.insertBefore(d,e)}(this,this.document,"yandexContextAsyncCallbacks");

Je zřejmé, že ne každý počítač a ne každý systém může být postaven schopni získat náhodné číslo na základě stochastického procesu. Použití náhodného řešení je proto v případě potřeby užitečné. Jeho práce můželiší se od systému k systému, od počítače po počítač a možná je zcela mimo dosah. Při použití generátoru skutečně náhodných čísel je proto nutné zajistit zpracování chyb.

Použití random_device jako osiva pro DSPF

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

V tomto kódu není nic nového. Současně se při každém spuštění DIRF inicializují náhodné hodnoty generované pravým generátorem náhodných čísel rd.

Je také třeba poznamenat, že inicializační hodnota generátoru může být kdykoliv vynulována:

e.seed (15027); //inicializujte podle čísla
e.seed (); //inicializujte na výchozí hodnotu
e.seed (rd ()); //Inicializace jiným generátorem

Shrneme: generátory a distribuce

Generátor (motor) je objekt, který vám umožňuje vytvářet různá čísla pravděpodobnosti.

Distirbution je objekt, který konvertuje sekvenci čísel generovaných generátorem do distribuce podle konkrétního zákona, například:

  • jednotná (jednotná);
  • normální - Gaussova distribuce (normální);
  • binomický (binom) atd.

Zvažte generátory standardní knihovny C ++.

  1. Stačí, když začátečníci používají default_random_engine, ponecháním výběru generátoru do knihovny. Generátor bude vybrán na základě kombinace faktorů, jako je výkon, velikost, kvalita šance.
  2. Pro pokročilé uživatele poskytuje knihovna 9 předkonfigurovaných generátorů. Jsou velmi odlišné od sebeproduktivitu a velikost, ale současně byla jejich kvalita práce podrobena vážným zkouškám. Často se často používá oscilátor nazvaný motory Mersenne twister a jeho instance mt19937 (vytvoření 32bitových čísel) a mt19937_64 (vytvoření 64bitových čísel). Generátor je optimální kombinací rychlosti a stupně náhodnosti. Pro většinu výzev bude stačit.
  3. Knihovna pro odborníky poskytuje nakonfigurované šablony pro generátory, které umožňují vytváření dalších typů generátorů.

Zvažte klíčové aspekty distribucí. V normě jejich jazyka je 20 kusů. Ve výše uvedeném příkladu byla rovnoměrná distribuce náhodných knihoven C ++ v rozmezí [a, b] pro celé čísla použita jednotná_rozdělení. Tato distribuce může být použita pro reálná čísla: uniform_real_distribution se stejnými parametry a a b jako generace čísel. Současně jsou zahrnuty hranice mezery, tj. [A, b]. Seznam všech 20 distribucí a opakování C ++ dokumentace v článku nemá smysl.

Je třeba poznamenat, že každé rozdělení odpovídá jeho souboru parametrů. Pro rovnoměrné rozložení je to interval od a do b. A pro geometrický (geometric_distribution) parametr existuje pravděpodobnost úspěchu p.

Většina distribucí je definována jako šablona třídy, pro kterou je parametrem typ hodnot sekvence. Některé distribuce však vytvářejí sekvence pouze hodnoty int nebo pouze reálné hodnoty. Nebo například Bernoulliova sekvence (bernoulli_distribution) udává hodnotu typu bool. Stejně jako u MHF může uživatel knihovnyvytvořit vlastní distribuci a použití s ​​vloženými generátory nebo generátory, které vytvoří.

Knihovny v této funkci nejsou omezené. Jsou mnohem širší. Ale poskytnuté informace jsou dostatečné pro použití a základní pochopení generátoru náhodných čísel v jazyce C ++.

pozadí: Náhodný styl Net

Rámec NET je také přítomen Random třída ke generování náhodných čísel. Podívejme se na příklad generování náhodného čísla C ++ /CLI.

Pro ty, kteří pracují ve Visual Studio a nerozumí, proč není jmenný prostor systému definován.

Pro práci s .net je nutné připojit CLR. To se provádí ve dvou sposobamy.1) Vytvoření projektu není windows konzolová aplikace, a podporuje CLR - konzolová aplikace CLR (CLR aplikace konzoly) .2) podporu Connect CLR při stanovování existující projekt: Vlastnosti projektu (v rámci „projektu“, a nikoli " služba ") - & gt; konfigurace - & gt; obecně - & gt; výchozí hodnota - & gt; v rozevíracím seznamu Podpora pro obecné běhové prostředí (CLR) vyberte možnost "Podpora prostředí CLR (/clr)".

#include "stdafx.h"
#include

//using namespace System;

int main (array ^ args)
{
systému :: Náhodné ^ RND1 = gcnew System :: Náhodné (); //vytvořit MHF, ve výchozím nastavení se inicializuje podle aktuálního času
std :: cout rnd1- & Next () "n"; //vrátí kladné celé číslo

int horní = 50;
std :: cout rnd1- & Next (horní) "n"; //vrátí kladné celé číslo ne více než horní

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

int seed = 13977;
Systém :: Náhodný ^ rnd2 = gcnew Systém :: Náhodné (osivo); //inicializujte MHFpočet semen
std :: cout rnd2- & Next (5001000) n; //stejné číslo se vytvoří při každém spuštění programu.

std :: cout std :: endl;

návrat 0;
}

V tomto případě se veškerá práce provádí pomocí funkce Random Next C ++ /CLI.

Za zmínku stojí, že .net je velká knihovna s velkými schopnostmi a používá vlastní verzi jazyka C ++ /CLI z Common Language Infrastructure. Obecně jde o rozšíření C ++ na platformu .Net.

Vezměme na závěr několik příkladů, abychom lépe porozuměli práci s náhodnými čísly.

#include
#include
#include
int main () {
std :: mt19937 e1;
e1.seed (čas

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

std :: mt19937 e2 (čas

);

std :: mt19937 e3 {};
std :: jednotné_rozměrování 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ální rozdělení s průměrnou hodnotou 5,0 a střední střední kvadratická odchylka 2,0
std :: cout urd (e4), nd (e4) std :: endl;

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


Závěr

Všechny technologie a metody jsou neustále vyvíjeny a vylepšovány. To se také stalo s mechanismem generování náhodných čísel rand (), který je zastaralý a přestal splňovat moderní požadavky. V knihovně STL existuje libovolná knihovna, v .Net Framework - třídě Random, která pracuje s náhodnými čísly. Použití rand by mělo odmítnout výhody nových metod, protože odpovídají moderním programovým paradigmatům a staré metody budou vyloučeny z normy.

Související publikace