Algoritmus pro generování náhodných čísel

hlasů
7

Dívám se na generování náhodných čísel a vydat ho do tabulky v databázi pro konkrétní user_id. Úlovek je, stejný počet nelze použít dvakrát. Je tu milion způsobů, jak toho dosáhnout, ale já jsem doufal, že někdo velký zájem o algoritmy má chytrý způsob řešení problému v elegantní řešení v tom, že z těchto kritérií je splněno:

1) Nejmenší množství dotazů do databáze jsou vyrobeny. 2) nejméně množství procházení skrze strukturu dat do paměti se provádí.

V podstatě tato myšlenka je provést následující kroky

1) Vytvořte náhodné číslo od 0 do 9999999
2) Zkontrolujte databázi, aby zjistily, zda existuje číslo
OR
2) Dotaz databáze pro všechna čísla
3) Podívejte se, zda vrácené výsledek zápasy cokoliv přišli z db
4) Je-li tenisové opakování krok 1, pokud ne, je problém vyřešen.

Dík.

Položena 26/11/2008 v 02:44
zdroj uživatelem
V jiných jazycích...                            


17 odpovědí

hlasů
1

Myslím, že zjistíte, že opravdu nechci to dělat. Vzhledem k tomu, čísla v nárůstu databázi, možná budete trávit příliš mnoho času v „Ujistěte se, že toto číslo není brán“ smyčky.

Osobně jsem měl štěstí s hash jako alternativa, ale přijít s lepší řešení, tak bych opravdu potřebuji vědět, proč chcete dělat to takhle.

Odpovězeno 26/11/2008 v 02:51
zdroj uživatelem

hlasů
1

Moje zkušenost byla jednoduše pomocí RNG v PHP. Zjistil jsem, že použití určitého velikost čísla (já používám int, takže mám max 4G). Běžel jsem nějaké testy a zjistil, že v průměru na 500.000 iterací, mám 120 jednolůžkových duplikáty. Nikdy jsem si trojmo po spuštění smyčce spoustu časů. My „řešení“ bylo pak už jen vložit a zkontrolovat, zda to nepodaří, pak generovat nové ID a jít znovu.

Moje rada je, aby učinili totéž a zjistit, jaké jsou vaše kolizní míra a c a zjistit, jestli je to přijatelné pro váš případ.

To není optimální, takže pokud má někdo návrhy dívám taky :)

EDIT: I byl omezen pouze na 5-ti místný ID ([a-za-z0-9] {5,5}), tím delší je id (více kombinací, na několik kolizí). MD5 e-mailu by téměř nikdy v rozporu, např.

Odpovězeno 26/11/2008 v 02:51
zdroj uživatelem

hlasů
17

Ne váš algoritmus není škálovatelné. To, co jsem udělal, než je vydávání čísel sériově (+1 pokaždé) a poté je předávají prostřednictvím operace XOR se míchanice bitů tím mi dala zdánlivě náhodných čísel. Samozřejmě, že ve skutečnosti nejsou náhodné, ale vypadají tak, aby uživatelé očí.


[Edit] Další informace

Logika tohoto algoritmu je to takhle použít známou sekvenci generovat jedinečná čísla a pak deterministicky manipulovat s nimi, takže nevypadají serial už ne. Obecné řešení je použít nějakou formu šifrování, což v mém případě byl XOR flipflop, protože je tak rychle, jak to může dostat, a to plní záruku, že čísla nikdy srazit.

Můžete však použít i jiné formy šifrování, pokud chcete raději ještě více náhodných vypadající čísla, než rychlost (říkat nemusíte generovat mnoho IDS najednou). Nyní je důležitým bodem při výběru šifrovací algoritmus je „zárukou, že čísla nikdy se srazí“. A způsob, jak dokázat, pokud šifrovací algoritmus může splnit tuto záruku, je zkontrolovat, zda oba původní číslo a výsledek šifrování mají stejný počet bitů a že algoritmus je reverzibilní (bijekce).

[Díky Adam Liss & CesarB pro exapanding na řešení]

Odpovězeno 26/11/2008 v 02:51
zdroj uživatelem

hlasů
1

Problém je v tom, že pokud se generování náhodných čísel je velmi možné vyrobit duplikáty infinatly.

nicméně:

<?php
//Lets assume we already have a connection to the db
$sql = "SELECT randField FROM tableName";
$result = mysql_query($sql);
$array = array();
while($row = mysql_fetch_assoc($result))
 {
   $array[] = $row['randField'];
 }
while(True)
 {
   $rand = rand(0, 999999);
   if(!in_array($rand))
     {
       //This number is not in the db so use it!
       break;
     }
 }
?>

I když to bude dělat to, co budete chtít taky, to není dobrý nápad, protože to není měřítko na dlouho, eventualy vaše pole dostane až po velké a bude trvat velmi dlouho, než generovat náhodná, která již není v db ,

Odpovězeno 26/11/2008 v 02:55
zdroj uživatelem

hlasů
2

Za předpokladu:

  • Náhodnost je potřeba pro jedinečnosti, ne pro bezpečnost
  • Váš user_id je 32 bit
  • Váš limit 9999999 byla jen příklad

Dalo by se něco jednoduchého jako mající náhodné číslo jako 64 bitové celé číslo, se horních 32 bitů, obsahující časovou značku (v řadě vložky) a dolních 32 bitů user_id. To by bylo jedinečné i pro více řádků se stejným uživatelem, pokud budete používat vhodné rozlišení na časové razítko v závislosti na tom, jak často budete přidávat nové řádky pro stejného uživatele. V kombinaci s jedinečným omezením na náhodném kolony a chytit žádnou takovou chybu v logice a pak už jen opakovat.

Odpovězeno 26/11/2008 v 03:00
zdroj uživatelem

hlasů
1

Je snadné vytvořit číslo pseudorandom generátor s dlouhým obdobím nonrepetition; např tenhle , který je používán pro stejnou věc, že ho chcete mít na.

BTW, proč ne jen vydávat postupně IDuživatele je?

Odpovězeno 26/11/2008 v 03:02
zdroj uživatelem

hlasů
0

PHP již má funkci pro to, uniqid . To vytváří standardní UUID, což je skvělé, pokud máte přístup k datům odkudkoli. Nepoužívejte znovu vynalézat kolo.

Odpovězeno 26/11/2008 v 03:06
zdroj uživatelem

hlasů
6

Chcete-over-the-top řešení?

Předpokládám, že náhodnost není určen k šifrování kvalitní, ale jen natolik, aby odradit hádání dlouhověkost uživatele tím, že user_id.

Během vývoje, vytvoří seznam všech 10 milionů čísel v řetězci formě.

Případně provést některé jednoduché transformace, jako je přidání konstantní řetězec do středu. (To je jen v případě, že výsledek je příliš předvídatelné.)

Předat je do nástroje, který vytváří perfektní Hash funkce , jako je například gperf .

Výsledný kód je možné použít k rychlému kódování ID uživatele za běhu do jedinečné hash hodnoty, která je zaručena není v rozporu s jinými hash hodnoty.

Odpovězeno 26/11/2008 v 03:16
zdroj uživatelem

hlasů
17

Proč ne jen používat GUID? Nejvíce jazyky by měl mít vestavěný způsob, jak to udělat. Je zaručena jedinečnost (s velmi rozumných mezích).

Odpovězeno 26/11/2008 v 03:19
zdroj uživatelem

hlasů
1

Líbí se mi Oddthinking myšlenku, ale namísto výběru nejsilnější hashovací funkci na světě, mohl jednoduše:

  • Generovat MD5 je prvních 10 milionů čísel (vyjádřené jako řetězce, + nějakou sůl)
  • Zkontrolovat duplicity v režimu offline , tedy před odchodem do výroby (Myslím, že nebude k dispozici)
  • Ukládat duplikáty v poli někde
  • Při spuštění aplikace, vložte pole
  • Pokud chcete vložit číslo, zvolte další číslo, počítat jeho MD5, zkontrolujte, zda je v poli, a není-li jej použít jako ID v databázi. V opačném případě zvolte další číslo

MD5 je tak rychlý, a kontroluje, zda řetězec patří do pole se vyhnout ti SELECT.

Odpovězeno 26/11/2008 v 03:41
zdroj uživatelem

hlasů
3

Zkuste příkaz v mysql SELECT CAST (rand () * 1000000 AS INT)

Odpovězeno 26/11/2008 v 08:51
zdroj uživatelem

hlasů
1

Já jsem vlastně předtím napsal článek o tom . To vyžaduje stejný přístup jako Roberta Goulda odpověď, ale navíc ukazuje, jak zkrátit blokovou šifru na vhodnou délku pomocí xor skládací, a pak, jak generovat permutace v rozsahu, který není mocninou 2, a zároveň zachování jedinečnost majetku.

Odpovězeno 26/11/2008 v 11:13
zdroj uživatelem

hlasů
0

Asi jsem nezachytil své místo, ale co auto_increments?

Odpovězeno 27/11/2008 v 19:11
zdroj uživatelem

hlasů
1

Pokud opravdu chcete dostat „náhodná“ čísla forma 0-9 999 999, pak řešení je dělat „náhodného“ jednou a pak uložit výsledek na disk.

Není to těžké získat požadovaný výsledek, ale myslím, že to spíš jako „vytvořit dlouhý seznam s čísly“, než „získat náhodné číslo“.

$array = range(0, 9999999);
$numbers = shuffle($array);

Také je potřeba ukazatel na aktuální pozici v $ čísel (uložte jej v databázi); začínat 0 a zvyšovat ji pokaždé, když potřebujete nové číslo. (Nebo můžete použít array_shift () nebo array_pop (), pokud nemáte rádi používají ukazatele).

Odpovězeno 27/11/2008 v 23:41
zdroj uživatelem

hlasů
1

Algoritmus správný PRNG (Pseudo-generátor náhodných čísel), bude mít časový cyklus, během kterého to nikdy nebude ve stejném stavu. Máte-li vystavit celý stav PRNG v počtu načtena z něj dostanete číslo zaručenou jedinečné po dobu generátoru.

Jednoduchý PRNG, který toto se nazývá ‚ Linear congruential ‘ PRNG který opakuje vzorec:

X(i) = AX(i-1)|M

Pomocí pravého dvojice faktorů můžete získat dobu 2 ^ 30 (cca 1 miliarda) od jednoduchého PRNG s 32 bitů akumulátoru. Všimněte si, že budete potřebovat 64 bit long dočasné proměnné držet prostřední část ‚AX‘ z výpočtu. Většina, ne-li všechny kompilátory C bude podporovat tento typ dat. Také byste měli být schopni to udělat s číselný datový typ u většiny SQL dialektů.

Se správnými hodnotami A a M můžeme získat generátor náhodných čísel s dobrými statistické a geometrické vlastnosti. Tam je slavný dokument o tom viz Fishman a Moore.

Pro m = 2 ^ 31 až 1 dostaneme použít hodnoty níže uvedená získat PRNG s pěknou dlouhou dobu (2 ^ 30 IIRC).

Dobrými hodnotami:

742,938,285  
950,706,376  
1,226,874,159  
62,089,911  
1,343,714,438   

Všimněte si, že tento typ generátoru je (podle definice), není kryptograficky bezpečný. Pokud víte, že poslední číslo generované z něj můžete předpovědět, co bude dělat dál. Bohužel se domnívám, že se nemůžete dostat šifrovací bezpečnost a záruku neopakovatelnosti najednou. Pro PRNG být kryptograficky zabezpečené (např Blum Blum Shub ) nemůže vystavit dostatečný stav v generované číslo na další číslo v pořadí, aby se předpovědět. Proto je vnitřní stav je širší než vygenerované číslo a (aby měl dobré zabezpečení) lhůta bude delší, než je počet možných hodnot, které mohou být generovány. To znamená, že exponovaná číslo nebude ojedinělý ve stanovené lhůtě.

Z podobných důvodů, že totéž platí o dlouhou periodou generátorů, jako jsou Mersenne Twister.

Odpovězeno 27/11/2008 v 23:59
zdroj uživatelem

hlasů
1

Existuje několik způsobů, jak jít o tom jeden způsob, jak by bylo postavit pole s čísly 0000000 až 9999999 a pak vybrat náhodný výběr z těchto čísel na tomto poli a prohodit vybral čísla hodnoty s nejvyšší hodnotou Max pak snížila max by 1 a vybrat jiný náhodný člen tohoto pole na novém maximu

pokaždé snížení Max jedním

Například (v bazické): (napravo jsou komentáře, které by měly být odstraněny v aktuálním programu) Rndfunc je výzva na cokoliv náhodných čísel funkcí generátor, který používáte

dim array(0 to 9999999) as integer
for x% = 1 to 9999999
array(x%)=x%
next x%
maxPlus = 10000000
max =9999999
pickedrandom =int(Rndfunc*maxPlus)  picks a random indext of the array based on    
                                   how many numbers are left
maxplus = maxplus-1
swap array(pickedrandom) , array(max) swap this array value to the current end of the
                                     array 
max = max -1                   decrement the pointer of the max array value so it 
                              points to the next lowest place..

pak to dělat to pro každé číslo, které chcete vybrat, ale budete muset mít možnost používat velmi velké matice

druhá metoda by být následující: generování množství a uložit ji do pole, které může růst dynamicky pak po vyzvednutí nového čísla a porovnat jej s hodnotou, která je v polovině od prvního do posledního prvku v poli v tomto případě to by byl první číslo vybral, zda odpovídá vyzvednout další náhodné číslo, třídit pole podle velikosti a pokud není shoda pak v závislosti na počasí je větší nebo menší, než je číslo, které je ve srovnání s tebou jít nahoru nebo dolů seznam polovina poloviční vzdálenosti, pokaždé, když to neodpovídá a je větší nebo menší než to, co se to ve srovnání s.

Pokaždé, když na polovinu, dokud nedosáhnete velikosti mezery jednoho pak zkontrolovat jednou a zastaví, neexistuje žádná shoda, a pak se přidá další číslo do seznamu a seznam je zamíchal ve vzestupném pořadí, a tak dále a tak dále, dokud si nejste provádí sběr náhodných čísel ... doufám, že to pomůže ..

Odpovězeno 27/01/2012 v 14:05
zdroj uživatelem

hlasů
0

Chcete-li zajistit, aby náhodných čísel se neopakuje, budete potřebovat neopakující náhodných čísel-generátor (jak je popsáno zde ).

Základní myšlenkou je, že následující vzorec seed * seed & pbude produkován neopakující náhodných čísel pro jakéhokoli vstupu x such that 2x < pa p - x * x % pprodukuje všechny ostatní náhodných čísel aswell neopakující se, ale pouze v případě, p = 3 mod 4. Takže v podstatě vše, co potřebujete, je jeden primnumber tak blízko 9999999, jak je to možné. Tímto způsobem snaha může být snížena na jediném čtení pole, ale s druhou stranu, že buď příliš velké identifikátory jsou vytvářeny nebo bude vygenerován příliš málo ID.

Tento algoritmus není permutaci velmi dobře, takže bych doporučil kombinovat to buď XOR nebo přidáním nebo nějaký jiný přístup ke změně přesnou hodnotu bez zničení 1-to-1-vztah mezi semeny a jejich generované hodnoty.

Odpovězeno 04/10/2015 v 22:49
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more