Algorithmus zum Erzeugen einer Zufallszahl

stimmen
7

Ich suche eine Zufallszahl zu erzeugen und zu einer Tabelle in einer Datenbank für einen bestimmten User_id zu erteilen. Der Fang wird, die gleiche Nummer kann nicht zweimal verwendet werden. Es gibt eine Million Möglichkeiten, dies zu tun, aber ich bin die Hoffnung, jemand sehr daran interessiert, auf Algorithmen zur Lösung des Problems in einer eleganten Lösung darin, dass die folgenden Kriterien eine clevere Art und Weise hat erfüllt ist:

1) Die geringste Menge an Anfragen an die Datenbank gestellt werden. 2) die geringste Menge an Kriechen durch eine Datenstruktur im Speicher vorgenommen wird.

Im Grunde ist die Idee, die folgendes zu tun

1) Erstellen Sie eine Zufallszahl 0-9999999
2) Überprüfen Sie die Datenbank, ob die Zahl existiert
OR
2) Abfrage der Datenbank für alle Zahlen
3) Prüfen Sie , ob die zurückgegebenen Ergebnis passt , was aus der db kam
4) Wenn es zutrifft, wiederholen Schritt 1, wenn nicht, wird Problem gelöst.

Vielen Dank.

Veröffentlicht am 26/11/2008 um 02:44
quelle vom benutzer
In anderen Sprachen...                            


17 antworten

stimmen
1

Ich glaube, Sie werden feststellen, dass Sie wirklich nicht wollen, dies zu tun. Da die Zahlen in der Datenbank zu erhöhen, könnten Sie Schleife zu viel Zeit in der „diese Zahl nicht genommen wird sicherstellen, dass“ verbringen.

Persönlich habe, habe ich Glück mit Hashes als Alternative, aber mit einer besseren Lösung zu kommen, würde ich wirklich wissen müssen, warum Sie es auf diese Weise tun wollen.

Beantwortet am 26/11/2008 um 02:51
quelle vom benutzer

stimmen
1

Meine Erfahrung war einfach mit der RNG in PHP. Ich fand, dass eine bestimmte Größe von Nummer (ich einen int bin mit, so dass ich ein Maximum von 4G). Ich lief einige Tests und festgestellt, dass im Durchschnitt in 500.000 Iterationen ich 120 einzelne Duplikate bekam. Ich habe nie eine dreifache Ausfertigung nach der Schleife ein paar Mal ausgeführt wird. Meine „Lösung“ war dann legen Sie einfach und überprüfen, ob es fehlschlägt, dann eine neue ID generiert und wieder gehen.

Mein Rat ist, das Gleiche zu tun und sehen, was Ihre Kollisionsrate ist & c und sehen, ob es für Ihren Fall akzeptabel ist.

Dies ist nicht optimal, so dass, wenn jemand Vorschläge hat auch ich bin auf der Suche :)

EDIT: Ich war auf eine 5-stellige ID ([a-zA-Z0-9] {5,5}), desto länger ist die ID (mehr Kombination, die wenige Kollisionen). Ein md5 der E-Mail würde so gut wie nie in Konflikt geraten, zum Beispiel.

Beantwortet am 26/11/2008 um 02:51
quelle vom benutzer

stimmen
17

Nein Ihr Algorithmus ist nicht skalierbar. Was ich vorher getan ist Zahlen zur Ausgabe von seriell (+1 jedes Mal) und sich dann durch eine XOR-Operation passiert die Bits zu Durcheinander so mir eine scheinbar zufälligen Zahlen geben. Natürlich sind sie nicht wirklich zufällig, aber sie sehen so den Nutzern Augen.


[Bearbeiten] Weitere Informationen

Dieser Algorithmus Logik geht so Sie eine bekannte Sequenz verwenden eindeutige Zahlen zu erzeugen und dann manipulieren Sie determinis sie, so sehen sie nicht mehr seriell. Die allgemeine Lösung ist eine Form der Verschlüsselung zu verwenden, die in meinem Fall ein XOR-Flip-Flop war, weil seine so schnell, wie es bekommen kann und es die Garantie erfüllt, die Zahlen werden nie kollidieren.

Sie können jedoch andere Formen der Verschlüsselung verwenden, wenn Sie noch mehr zufällige suchen Zahlen vorziehen wollen, über Geschwindigkeit (sagen Sie nicht viele IDs zu einer Zeit zu erzeugen, benötigen). Jetzt ist der wichtige Punkt einen Verschlüsselungsalgorithmus bei der Wahl ist „die Garantie, die Zahlen werden nie kollidieren“. Und ein Weg, um zu beweisen, wenn ein Verschlüsselungsalgorithmus diese Garantie erfüllen kann, ist sowohl zu überprüfen, ob die ursprüngliche Zahl und das Ergebnis der Verschlüsselung die gleiche Anzahl von Bits haben, und dass die der Algorithmus ist reversibel (Bijektion).

[Dank Adam Liss & CesarB für exapanding auf die Lösung]

Beantwortet am 26/11/2008 um 02:51
quelle vom benutzer

stimmen
1

Das Problem ist, dass, wenn Sie Zufallszahlen zu erzeugen ist sehr möglich Duplikate infinatly zu produzieren.

jedoch:

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

Während dies tun, was Sie es zu wollen, ist es eine schlechte Idee, da dies nicht für lange skaliert, eventualy Ihr Array zu groß werden und es wird eine extrem lange Zeit in Anspruch nehmen eine zufällige, dass nicht bereits in Ihrem db zu erzeugen .

Beantwortet am 26/11/2008 um 02:55
quelle vom benutzer

stimmen
2

Unter der Annahme:

  • Die Zufälligkeit ist für Eindeutigkeit erforderlich ist, nicht für die Sicherheit
  • Ihre user_id ist 32 Bit
  • Ihr Limit von 9999999 war nur ein Beispiel

Man könnte etwas Einfaches wie mit der Zufallszahl als eine 64-Bit-Ganzzahl, wobei die oberen 32 Bits enthalten, den Zeitstempel (in Zeile insert) und die unteren 32 Bits des User_id tun. Das wäre auch für mehrere Zeilen mit demselben Benutzer eindeutig sein, sofern Sie eine entsprechende Auflösung auf Ihrem Zeitstempel verwenden, je nachdem, wie oft Sie neue Zeilen für den gleichen Benutzer hinzuzufügen. Kombinieren Sie mit einer einzigartigen Einschränkung für die zufällige Spalte und fangen einen solchen Fehler in der Logik und dann einfach wiederholen.

Beantwortet am 26/11/2008 um 03:00
quelle vom benutzer

stimmen
1

Es ist einfach , einen Pseudo - Zufallszahlengenerator mit einer langen Periode von nonrepetition zu entwerfen; zB dies ein , die für die gleiche Sache verwendet wird , dass Sie es für wollen.

BTW, warum nicht nur die Reihe nach der Benutzer-ID ausgeben?

Beantwortet am 26/11/2008 um 03:02
quelle vom benutzer

stimmen
0

PHP hat bereits eine Funktion dafür, uniqid . Es erzeugt einen Standard - UUID , die groß ist , wenn Sie die Daten aus anderen Ländern zuzugreifen. Das Rad nicht neu erfinden.

Beantwortet am 26/11/2008 um 03:06
quelle vom benutzer

stimmen
6

Möchten Sie eine Over-the-Top-Lösung?

Ich gehe davon aus Zufälligkeit ist nicht als Verschlüsselung Qualität bestimmt ist, aber gerade genug, um zu entmutigen, die Langlebigkeit eines Benutzers zu erraten, von user_id.

Während der Entwicklung erzeugt eine Liste aller 10 Millionen Zahlen in String-Form.

Optional kann eine einfache Transformation durchführt, wie ein konstanten String in die Mitte hinzufügen. (Dies ist für alle Fälle ist das Ergebnis zu vorhersehbar.)

Übergeben sie in ein Werkzeug , das erzeugt perfekte Hash - Funktionen , wie gperf .

Der resultierende Code kann schnell verwendet werden, um die ID zur Laufzeit in einen eindeutigen Hash-Wert des Benutzers zu kodieren, die garantiert nicht mit anderen Hash-Werten kollidieren.

Beantwortet am 26/11/2008 um 03:16
quelle vom benutzer

stimmen
17

Warum gehst du nicht einfach eine GUID verwenden? Die meisten Sprachen sollte eine eingebaute Möglichkeit, dies zu tun. Es ist garantiert einzigartig (mit sehr vernünftigen Grenzen) zu sein.

Beantwortet am 26/11/2008 um 03:19
quelle vom benutzer

stimmen
1

Ich mag Oddthinking Idee, aber anstatt die stärkste Hash-Funktion in der Welt wählen, könnten Sie einfach:

  • Generieren Sie den MD5-Wert der ersten 10 Millionen von Zahlen (als Strings ausgedrückt, + etwas Salz)
  • Prüfen Sie nach Duplikaten offline , dh vor in Produktion gehen (ich denke , es wird keine geben)
  • Speichern der Duplikate in einem Array irgendwo
  • Wenn die Anwendung gestartet wird, laden Sie das Array
  • Wenn Sie eine ID einfügen möchten, wählen Sie die nächste Nummer, berechnen die MD5, überprüfen, ob es in dem Array ist, und wenn es sie nicht als ID in der Datenbank verwenden. Andernfalls wählen Sie die nächste Nummer

MD5 ist schnell, und prüfen, ob ein String in ein Array gehört werden Sie eine SELECT vermeiden.

Beantwortet am 26/11/2008 um 03:41
quelle vom benutzer

stimmen
3

Versuchen Sie, die Anweisung in mysql SELECT CAST (RAND () * 1000000 AS INT)

Beantwortet am 26/11/2008 um 08:51
quelle vom benutzer

stimmen
1

Ich habe vorher tatsächlich geschrieben einen Artikel über diese . Es nimmt den gleichen Ansatz wie Robert Gould Antwort, sondern zusätzlich zeigt , wie ein Blockchiffre auf eine geeignete Länge mit xor Falten zu verkürzen, und dann , wie die Permutationen über einen Bereich zu erzeugen , die nicht eine Potenz von 2 ist, während nach wie vor die Erhaltung Einzigartigkeit Eigenschaft.

Beantwortet am 26/11/2008 um 11:13
quelle vom benutzer

stimmen
0

Ich habe wahrscheinlich die Stelle nicht fangen, aber was ist auto_increments?

Beantwortet am 27/11/2008 um 19:11
quelle vom benutzer

stimmen
1

Wenn Sie wirklich „zufällig“ Zahlen von 0 bis 9 999 999, erhalten möchten, dann ist die Lösung, die die „Randomisierung“ einmal zu tun, und dann speichern Sie das Ergebnis auf Ihre Festplatte.

Es ist nicht schwer, das gewünschte Ergebnis zu bekommen, aber ich denke, es eher wie „eine lange Liste mit Zahlen machen“, als „eine Zufallszahl erhalten“.

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

Sie müssen auch einen Zeiger auf aktuelle Position in $ Nummern (speichern sie in einer Datenbank); mit 0 beginnen und es jedes Mal, wenn Sie eine neue Nummer benötigen erhöhen. (Oder Sie könnten verwenden array_shift () oder array_pop (), wenn Sie nicht Zeiger verwenden möchten.)

Beantwortet am 27/11/2008 um 23:41
quelle vom benutzer

stimmen
1

Ein richtige PRNG (Pseudo-Random Number Generator) Algorithmus wird eine Zykluszeit hat, während die sie nie im gleichen Zustand sein. Wenn Sie den gesamten Zustand des PRNG in der von ihm abgerufenen Zahl aussetzen, finden Sie eine Reihe garantiert eindeutig für den Zeitraum des Generators erhalten.

Eine einfache PRNG , die dies tut , ist das ‚genannt lineare Kongruenz ‘ PRNG , die eine Formel iteriert:

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

das richtige Paar von Faktoren verwenden, können Sie über einen Zeitraum von 2 ^ 30 (ca. 1 Mrd. Euro) aus einem einfachen PRNG mit einem 32-Bit-Akkumulator erhalten. Beachten Sie, dass Sie einen 64-Bit lange lange temporären Variable benötigen, um das Zwischen ‚AX‘ Teil der Berechnung zu halten. Die meisten, wenn nicht alle C-Compiler wird diese Datentypen unterstützen. Sie sollten es auch mit einem numerischen Datentyp auf den meisten SQL-Dialekte der Lage zu tun.

Mit den richtigen Werten von A und M können wir einen Zufallszahlengenerator mit guten statistischen und geometrischen Eigenschaften erhalten. Es gibt ein berühmtes Papier darüber geschrieben von Fishman und Mooren.

Für M = 2 ^ 31-1 erhalten wir die Werte von A unten verwenden, um eine PRNG mit einem schönen langen Zeitraum (2 ^ 30 IIRC) zu erhalten.

Gute Werte von A:

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

Beachten Sie, dass diese Art von Generator ist (per Definition) nicht kryptographisch sicher. Wenn Sie die letzte Nummer generiert daraus wissen kann man vorhersagen , was sie als nächstes tun wird. Leider glaube ich , dass Sie nicht Verschlüsselungssicherheit und garantiert Nichtwiederholbarkeit zugleich erhalten. Für ein PRNG kryptographisch sicher zu sein (zB Blum Blum Shub ) es kann nicht ausreichend in einem Zustand erzeugte Zahl belichten die nächste Zahl in der Folge zu ermöglichen , vorhergesagt werden. Daher wird der innere Zustand breiter ist als die erzeugte Zahl und (um eine gute Sicherheit zu haben) die Frist länger sein als die Anzahl der möglichen Werte , die erzeugt werden können. Dies bedeutet , dass die freigelegte Zahl wird innerhalb der Frist nicht eindeutig sein.

Aus ähnlichen Gründen ist das gleiche gilt für die Langperiodengeneratoren wie der Mersenne - Twister.

Beantwortet am 27/11/2008 um 23:59
quelle vom benutzer

stimmen
1

es gibt ein paar Möglichkeiten, um über diesen einen Weg zu gehen, wäre ein Array mit den Zahlen 0000000 bis 9999999 zu konstruieren und dann eine zufällige Wahl dieser Zahlen in diesem Array holen und die aufgenommenen Zahlen Werte mit dem höchsten Wert tauschen Max dann max reduzieren 1 und anderen Zufall Mitglied dieses Aufnahmegruppierungs auf den neuen Maximal

jedes Mal reduziert Max durch eine

zum Beispiel (in basic): (auf der rechten Seite sind Kommentare, die in dem eigentlichen Programm entfernt werden sollte) Rndfunc ist ein Aufruf an was auch immer Zufallszahlengenerator-Funktion verwenden Sie

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

dies zu tun Sie für jede Zahl dann halten holen wollen, aber Sie werden die Möglichkeit, mit sehr großen Arrays haben müssen

das andere Verfahren würde wie folgt aussehen: eine Zahl generieren und sie in ein Array speichern, die dynamisch wachsen dann kann danach eine neue Nummer wählen, und es zu dem Wert vergleichen, die in der Anordnung in diesem Fall auf halber Strecke vom ersten bis zum letzten Element ist es wäre die erste Zahl gepflückt, wenn sie paßt eine andere Zufallszahl auswählen, sortiert das Array nach Größe und wenn es keine Übereinstimmung ist dann je nach Wetterlage es größer oder kleiner als die Zahl ist, dass Sie es im Vergleich mit Sie gehen nach oben oder unten in die folgenden Liste der Hälfte der Hälfte der Strecke, jedes Mal, wenn es nicht paßt und ist mehr oder weniger als das, was Sie es zu vergleichen.

jedes Mal zu halbieren, bis Sie eine Lücke Größe eines erreichen dann, wenn Sie überprüfen und stoppen, da es keine Übereinstimmung gibt, und dann wird die Zahl auf der Liste und der Liste hinzugefügt wird in aufsteigender Reihenfolge neu gemischt, so weiter und so weiter, bis Sie Kommissionierung Zufallszahlen getan ... hoffe, das hilft ..

Beantwortet am 27/01/2012 um 14:05
quelle vom benutzer

stimmen
0

Wenn Sie , dass die Zufallszahlen sicherstellen wollen , nicht zu wiederholen, müssen Sie einen nicht-wiederkehrenden Zufallszahlengenerator (wie hier ).

Die Grundidee ist , dass die folgende Formel seed * seed & pfür jede Eingabe erzeugt wird , Zufallszahlen nicht wiederholenden x such that 2x < pund p - x * x % pproduziert alle anderen Zufallszahlen aswell nicht wiederholenden, aber nur , wenn p = 3 mod 4. Also im Grunde alles , was Sie brauchen , ist ein einziger primnumber so nahe 9999999wie möglich. Auf diese Weise kann der Aufwand auf ein einziges Lesefeld reduziert werden, aber mit dem Nachteil , dass entweder zu groß IDs generiert werden , oder zu wenige IDs generiert.

Dieser Algorithmus ist permutieren nicht sehr gut, ich würde so empfehlen es entweder mit XOR oder Additions- oder einem anderen Ansatz, den genauen Wert zu ändern, ohne die 1-zu-1-Beziehung zwischen Samen und deren erzeugten Wert zu zerstören.

Beantwortet am 04/10/2015 um 22:49
quelle vom benutzer

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