Generáló algoritmus egy véletlen számot

szavazat
7

Én keresem, hogy generál egy véletlen számot és kiadja azt az asztalon egy adatbázis egy adott user_id. A fogás van, ugyanazt a számot nem lehet használni kétszer. Van egy millió módja van ennek, de remélem, hogy valaki nagyon szívesen algoritmusok egy ügyes módja a probléma megoldásának egy elegáns megoldás, hogy a következő feltételek valamelyike ​​teljesül:

1) A legkevesebb lekérdezések az adatbázis készül. 2) A legkevesebb mászik át egy adatstruktúra a memóriában készül.

Lényegében az ötlet, hogy végezze el az alábbi

1) létrehozása egy véletlen számot 0-9999999
2) Ellenőrizze az adatbázis, hogy ha a szám létezik
, VAGY
2) lekérdezi az adatbázist az összes szám
3) Lásd: Ha a visszaadott eredmény egyezés bármilyen származott db
4) Ha egyezik, akkor ismételje 1. lépés, ha nem, a probléma megoldódott.

Kösz.

A kérdést 26/11/2008 02:44
a forrás felhasználó
Más nyelveken...                            


17 válasz

szavazat
1

Azt hiszem, rájössz, hogy tényleg nem akarom ezt. A számok az adatbázisban növekedés, akkor lehet, túl sok időt töltenek a „győződjön meg róla, ez a szám nem hozott” hurok.

Személy szerint én már volt szerencsém a hash alternatívájaként, de felér egy jobb megoldás, én igazán tudnia kell, miért szeretné ezt így.

Válaszolt 26/11/2008 02:51
a forrás felhasználó

szavazat
1

Saját tapasztalat egyszerűen az RNG PHP. Azt találták, hogy egy bizonyos méretű szám (általam használt int, úgyhogy max 4G). Futottam néhány vizsgálatot, és megállapította, hogy átlagosan 500.000 ismétléseket, kaptam 120 egységes ismétli. Sosem három párhuzamos futtatása után a hurok egy csomó alkalommal. Saját „megoldás” az volt, hogy akkor csak helyezze, és ellenőrizze, ha ez nem sikerül, akkor létrehoz egy új azonosítót és megint.

A tanácsom az, hogy nem ugyanaz, és mi a ütközési gyakoriság & c és lát ha ez elfogadható az Ön esetében.

Ez nem optimális, tehát ha valaki javaslatokat keresem is :)

EDIT: I korlátozódott 5 jegyű azonosító ([a-zA-Z0-9] {5,5}), a hosszabb id (több kombinációja, a kevés ütközések). Md5 az email szinte soha ütközik, például.

Válaszolt 26/11/2008 02:51
a forrás felhasználó

szavazat
17

Nem az algoritmus nem méretezhető. Amit eddig csináltunk, hogy kiadja a számok sorosan (1 minden alkalommal), majd átengedi egy XOR művelet összekever bitek ezáltal nekem egy látszólag véletlenszerű számokat. Természetesen ezek nem igazán véletlen, de úgy néznek ki úgy, hogy a felhasználók szemében.


[Edit] További információk

Ez az algoritmus logikája is, mint ez használ egy ismert szekvencia lehet egyedi számokat, és akkor meghatározottan manipulálják őket, így nem néz soros többé. Az általános megoldás az, hogy valamilyen formában a titkosítást, ami az én esetemben volt egy XOR flipflop, mert olyan gyors, mint ez is kap, és ez megfelel a garancia arra, hogy a számok soha nem fog ütközni.

Azonban akkor más formái titkosítást, ha azt szeretnénk, inkább még véletlen látszó számokat, több sebesség (mondjuk nem kell generálni sok ids egy időben). Most az a fontos kiválasztásában egy titkosító algoritmus „a garancia arra, hogy a számok soha nem fog ütközni”. És olyan módon, hogy bizonyítani, ha egy titkosítási algoritmus képes teljesíteni ezt a garanciát, hogy ellenőrizze, ha mind az eredeti számot, és az eredmény a titkosítást azonos bitek száma, és hogy az az algoritmus visszafordítható (bijekciót).

[Köszönet Adam Liss & CesarB számára exapanding a megoldás]

Válaszolt 26/11/2008 02:51
a forrás felhasználó

szavazat
1

A probléma az, hogy ha a véletlen szám generálás is nagyon lehetséges, hogy készítsen másolatokat infinatly.

azonban:

<?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;
     }
 }
?>

Bár ez is megteszi, amit akar túl, hogy ez egy rossz ötlet, mivel ez nem méretarányos sokáig, eventualy a tömb lesz a nagy, és elviszi egy rendkívül hosszú ideig, hogy létrehoz egy véletlenszerű, hogy nincs már a db .

Válaszolt 26/11/2008 02:55
a forrás felhasználó

szavazat
2

Feltételezve, hogy:

  • A véletlenszerűséget szükséges egyediségét, nem biztonsági
  • A user_id 32 bit
  • A határ 9999999 csak egy példa

Megteheted valami egyszerű, mint amelyek a véletlenszerű számot egy 64 bites egész szám, a felső 32 bit, amely a timestamp (ROW betét) és az alsó 32 bit a user_id. Ez lenne is egyedülálló több sor ugyanazzal a felhasználói, feltéve, hogy használja ki a megfelelő felbontást a timestamp függően, hogy milyen gyakran új sorokat ugyanazon felhasználó. Keverjük össze egy egyedi korlátot a véletlen oszlop és a fogást minden ilyen hiba a logika és aztán csak újra.

Válaszolt 26/11/2008 03:00
a forrás felhasználó

szavazat
1

Ez könnyű, hogy tervezzen egy pszeudo-véletlen szám generátor hosszú idő nonrepetition; pl ez , amely jelenleg használt ugyanazt a dolgot, hogy azt szeretné, hogy.

BTW, miért nem adja ki a userid a sorban?

Válaszolt 26/11/2008 03:02
a forrás felhasználó

szavazat
0

PHP már egy ilyen funkcióval, uniqid . Ez létrehoz egy szabványos uuid ami nagyszerű, ha az adatokhoz való hozzáféréshez, mint másutt. Ne feltalálni a kereket.

Válaszolt 26/11/2008 03:06
a forrás felhasználó

szavazat
6

Szeretne egy over-the-top megoldás?

Gondolom véletlenszerűség nem célja, hogy a titkosítás minőségű, de csak annyira, hogy visszatartsa találgatás a hosszú élet egy felhasználó által user_id.

A fejlesztés alatt létrehoz egy listát az összes 10 millió szám string formában.

Adott esetben végezni néhány egyszerű transzformáció, mintha egy konstans szöveget a középső. (Ezt csak abban az esetben az eredmény túl kiszámítható.)

Át őket egy eszköz, amely létrehozza Tökéletes hash függvények , például gperf .

A kapott kódot lehet használni, hogy gyorsan kódolni a felhasználó azonosítóját a futás egy egyedi hash érték, amely garantáltan nem ütköznek más hash értékeket.

Válaszolt 26/11/2008 03:16
a forrás felhasználó

szavazat
17

Miért nem csak használja a GUID? A legtöbb nyelv kell egy beépített módja ennek. Ez garantáltan egyedi (nagyon ésszerű határokat).

Válaszolt 26/11/2008 03:19
a forrás felhasználó

szavazat
1

Szeretem Oddthinking ötlete, de ahelyett, hogy az legerősebb hash függvény a világon, akkor egyszerűen:

  • Létrehoz a MD5 azon az első 10 millió szám kifejezve (húrok, + egy kis sót)
  • Ellenőrizze ismétlődések elérhető , vagyis mielőtt a termelés (Gondolom, nem lesz ilyen)
  • Tárolja az ismétlődések tömb valahol
  • Ha az alkalmazás elindul, betölti a tömb
  • Ha azt szeretnénk, hogy helyezzen be egy azonosítót, válassza ki a következő számot, kiszámítja a MD5, ellenőrizze, hogy a tömbben, és ha ez nem használhatja az azonosító az adatbázisban. Ellenkező esetben válassza a következő számot

MD5-k gyors, és ellenőrizni, hogy egy string tartozik tömb elkerülhető egy SELECT.

Válaszolt 26/11/2008 03:41
a forrás felhasználó

szavazat
3

Próbálja ki a nyilatkozatot mysql SELECT CAST (RAND () * 1000000 AS INT)

Válaszolt 26/11/2008 08:51
a forrás felhasználó

szavazat
1

Már tényleg korábban írt egy cikket erről . Tart a megközelítést Robert Gould választ, de emellett bemutatja, hogyan kell rövidíteni a tömbrejtjelezésnél a megfelelő méretre xor összecsukható, majd hogyan kell létrehozni a permutációk egy olyan tartományban, amely nem 2 hatványa, miközben továbbra is a egyediségét tulajdon.

Válaszolt 26/11/2008 11:13
a forrás felhasználó

szavazat
0

Valószínűleg nem értettem a lényeget, de mi a helyzet auto_increments?

Válaszolt 27/11/2008 19:11
a forrás felhasználó

szavazat
1

Ha szeretné, hogy „véletlen” számok formájában 0-9 999 999, akkor a megoldás az, hogy nem a „randomizáció” egyszer, majd tárolja az eredményt a lemezre.

Ez nem nehéz, hogy a kívánt eredményt, de én inkább úgy gondolok, mint a „hogy egy hosszú listát a számok”, mint a „véletlen számot kapj.”

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

Akkor is kell egy mutatót az aktuális pozíció $ számok (tárolja egy adatbázisban); 0-val kezdődik, majd megnöveli eggyel minden alkalommal, amikor szükség van egy új számot. (Vagy ha lehet használni array_shift () vagy array_pop (), ha nem szeretné használni mutatók.)

Válaszolt 27/11/2008 23:41
a forrás felhasználó

szavazat
1

A megfelelő PRNG (pszeudo-véletlenszám-generátor) algoritmus lesz a ciklus ideje alatt, amely soha nem lesz ugyanaz az állam. Ha ki az egész állam a PRNG számának kinyerni róla, akkor kap egy számot garantált egyedi időszakra a generátor.

Egy egyszerű PRNG, hogy nem ez az úgynevezett „ lineáris kongruencia ” PRNG amely lépked a képlet:

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

A megfelelő pár tényező lehet kapni egy 2 ^ 30 (körülbelül 1 milliárd forint) egy egyszerű PRNG egy 32 bites akkumulátor. Vegye figyelembe, hogy szüksége lesz egy 64 bit hosszú, hosszú átmeneti változó, hogy tartsa a köztes „AX” a számítás részben. A legtöbb, ha nem minden C fordító támogatni fogja ezt a típusú adatokat. Akkor is meg kell tudni csinálni egy numerikus adattípus a legtöbb SQL nyelvjárások.

A megfelelő értékek és M kaphatunk véletlenszám generátor jó statisztikai és geometriai tulajdonságai. Van egy híres könyv erről írta Fishman és Moore.

M = 2 ^ 31-1 megkapjuk lehet használni az értékeket az alábbi A, hogy egy PRNG egy szép hosszú ideig (2 ^ 30 IIRC).

Jó értékeit:

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

Megjegyzendő, hogy ez a fajta generátor (definíció szerint) nem titkosított biztonságos. Ha tudja az utolsó számot generált azt tudja megjósolni, hogy mi lesz a következő lépés. Sajnos azt hiszem, hogy nem tud titkosított biztonsági és garantált nem ismételhetőség ugyanabban az időben. Egy PRNG hogy biztonságosan titkosított (pl Blum Blum Shub ) nem lehet kitenni megfelelő állapotban a generált számot, hogy a következő szám a sorrendben lehet megjósolni. Ezért a belső állapot szélesebb, mint a generált számot, és (annak érdekében, hogy jó a biztonság) az az időszak hosszabb lesz, mint a lehetséges értékek számát, amely létrejöhet. Ez azt jelenti, hogy az exponált szám nem lesz egyedi határidőn belül.

Hasonló okok miatt ugyanez igaz a hosszú ideig generátorok, mint a Mersenne Twister.

Válaszolt 27/11/2008 23:59
a forrás felhasználó

szavazat
1

van egy pár módja, hogy menjen ez az egy módja az lenne, hogy egy olyan tömböt a számok 0000000 keresztül 9999999 majd válasszon egy véletlenszerű választás ezeket a számokat a tömbbe és a swap szedett számok értékei a legmagasabb érték Max majd csökkenteni max szerint 1 és válasszon egy másik véletlenszerűen tagja ennek a tömb akár az új maximális

minden egyes alkalommal, csökkentve Max egy

például (az alap): (jobbra megjegyzések amelyeket el kell távolítani az aktuális program) Rndfunc egy hívást, hogy bármilyen véletlenszám-generátor funkció használata

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..

majd tartsa ezt minden kívánt számot felvenni, de akkor meg kell azt a lehetőséget, segítségével nagyon nagy tömbök

A másik módszer a következő lenne: létrehoz egy számot, és tárolja egy tömb, amely dinamikusan növekszik majd azt követően, hogy válasszon egy új számot, és hasonlítsa össze az érték, amely félúton van az elsőtől az utolsó elem a tömbben ebben az esetben ez lenne az első számot választotta, ha megegyezik válasszon másik véletlen szám, rendezni a tömböt, nagyságuk szerint, ha nincs egyezés, akkor az időjárástól függően, hogy nagyobb vagy kisebb, mint a szám, mint magával megy felfelé vagy lefelé a lista fele távolság fele, minden egyes alkalommal, hogy nem felel meg, és kisebb vagy nagyobb, mint amit összevetve a.

minden egyes alkalommal megfelezve, amíg el nem éri a rés mérete az egyik, akkor egyszer ellenőrizze és megáll, mivel nincs meccs, majd a szám felkerül a listára, és a lista újrakevert emelkedő sorrendben, így tovább és így tovább, amíg meg nem kész szedés véletlen számokat ... remélem ez segít ..

Válaszolt 27/01/2012 14:05
a forrás felhasználó

szavazat
0

Ha azt szeretnénk, hogy a véletlen számok nem ismétlődő, szüksége van egy nem ismétlődő véletlenszám-generátor (ahogy itt ).

Az alapötlet az, hogy a következő képlet seed * seed & plesz termelt nem ismétlődő véletlen számok bármilyen bemeneti x such that 2x < pés p - x * x % pgyártja az összes többi véletlenszám-aswell nem ismétlődő, de csak akkor, ha p = 3 mod 4. Tehát alapvetően minden amire szüksége van egy primnumber olyan közel 9999999, amennyire csak lehetséges. Így az erőfeszítés lehet csökkenteni egyetlen olvasási területen, de a hátránya, hogy vagy túl nagy azonosítók generálása, vagy túl kevés azonosítók fog generálni.

Ez az algoritmus nem permutálni nagyon jól, tehát én azt javasolnám, ötvözve azt sem XOR vagy kívül, vagy valamilyen más megközelítés, hogy módosítsa a pontos érték menne a 1-to-1-viszonyát magvak és az általuk generált értéket.

Válaszolt 04/10/2015 22:49
a forrás felhasználó

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