2009-02-03 21 views

Antwort

6

Ich nehme an, Sie mea n Pseudozufallszahlen. Die einfachste, die ich kenne (vom Schreiben von Videospielen auf alten Maschinen), funktioniert folgendermaßen:

seed = seed * 5 + 1;

Sie tun das jedes Mal, wenn zufällig aufgerufen wird, und dann verwenden Sie so viele niedrige Bits, die Sie möchten. * 5 + 1 hat die nette Eigenschaft (IIRC), jede Möglichkeit zu treffen, bevor es wiederholt wird, egal wie viele Bits Sie betrachten.

Der Nachteil ist natürlich seine Vorhersagbarkeit. Aber das spielte in den Spielen keine Rolle. Wir haben Zufallszahlen wie verrückt für alle möglichen Dinge gesammelt, und Sie würden nie wissen, welche Zahl als nächstes kommt.

Machen Sie ein paar Dinge parallel und kombinieren Sie die Ergebnisse. Dies ist ein linearer kongruenter Generator.

+0

Das sind schreckliche Entscheidungen von a, c und m! – derobert

+1

Haha. Ja, aber das erste Mal, dass ich diese Routine gesehen habe, war eine 1-MHz-Maschine. :-) – Nosredna

8

POSIX.1-2001 gibt das folgende Beispiel einer Implementierung von rand() und srand(), möglicherweise nützlich, wenn die gleiche Sequenz auf zwei verschiedenen Maschinen benötigt wird.

static unsigned long next = 1; 
/* RAND_MAX assumed to be 32767 */ 
int myrand(void) { 
    next = next * 1103515245 + 12345; 
    return((unsigned)(next/65536) % 32768); 
} 
void mysrand(unsigned seed) { 
    next = seed; 
} 
5

Aloha!

Mit manuell meinen Sie "nicht mit Computer" oder "schreibe meinen eigenen Code"?

Wenn es nicht Computer verwendet, können Sie Dinge wie Würfel, Zahlen in einer Tasche und all diese Methoden im Fernsehen gesehen, wenn sie Teams auswählen, gewinnen Bingo-Serie usw. Las Vegas ist mit diesen Methoden in Prozessen gefüllt (Spiele), die darauf abzielen, Ihnen schlechte Gewinnchancen und ROI zu geben. Sie können auch die großen RAND Buch bekommen und wenden sich an eine zufällig ausgewählte Seite:

http://www.amazon.com/Million-Random-Digits-Normal-Deviates/dp/0833030477

(auch für einige Belustigung, die Kritiken gelesen)

Für Ihren eigenen Code schreiben Sie beachten müssen, warum nicht mit dem System zur Verfügung gestellt RNG ist nicht gut genug. Wenn Sie ein modernes Betriebssystem verwenden, wird ein RNG für Benutzerprogramme verfügbar sein, die für Ihre Anwendung gut genug sein sollten.

Wenn Sie wirklich Ihre eigenen implementieren müssen, gibt es eine riesige Reihe von Generatoren zur Verfügung.Für Nicht-Sicherheitsanwendungen können Sie LFSR-Ketten, Congruent-Generatoren usw. betrachten. Unabhängig von der benötigten Verteilung (einheitlich, normal, exponentiell usw.) sollten Sie in der Lage sein, Algorithmusbeschreibungen und Bibliotheken mit Implementierungen zu finden.

Für Sicherheit Verwendung sollten Sie Dinge wie Yarrow/Fortuna die NIST SP 800-89 angegebenen PRNGs und RFC 4086 für gute Entropie Quellen suchen, die benötigt werden, um die PRNG zu füttern. Oder noch besser, verwenden Sie die im Betriebssystem, die sollte Sicherheit RNG Anforderungen erfüllen.

Die Implementierung von RNGs kann eine lustige Übung sein, wird aber sehr selten benötigt. Und erfinden Sie nicht Ihren eigenen Algorithmus, außer es ist für Spielzeuganwendungen. NICHT, wiederhole NICHT, RNGs für Sicherheitsanwendungen zu erfinden (zum Beispiel kryptografische Schlüssel erzeugen), zumindest wenn du Seripus lesen und untersuchen lässt. Du wirst es mir danken (hoffe ich).

+0

A nit: "Sie können auch das große RAND-Buch bekommen und auf eine zufällig ausgewählte Seite wechseln". Das wäre stark voreingenommen gegenüber den Zahlen, die sich in der Mitte des Buches oben auf der Seite befinden. Leute sind schreckliche RNGs. – Malvolio

+0

Wenn Sie sich auf eine bestimmte Seite eines Buchs mit echten Zufallszahlen begeben, wird das Ergebnis nicht beeinflusst, solange Sie die Zahlen nicht wiederverwenden, da die Zahlen in der Mitte des Buchs genauso zufällig sind wie die auf der Vorderseite. Die Wiederverwendung von Zahlen wird das Ergebnis beeinflussen, egal auf welcher Seite er sie auswählt. –

3

Hoffentlich bin nicht redundant, weil ich nicht alle Links gelesen habe, aber ich glaube, dass Sie ziemlich nah an True Zufallsgenerator bekommen können. heutzutage Systeme sind oft so komplex, dass selbst die besten Geeks brauchen viel Zeit zu verstehen whats happening innerhalb :)

öffnen Sie einfach Ihre Meinung und denken, wenn Sie einige globale Systemeigenschaft überwachen können, verwenden Sie es zu säen .. Wählen Sie ein Netzwerkpaket (nicht für Sie bestimmt?) und berechnen Sie "etwas" aus seinem Inhalt und verwenden Sie es zu ...

Sie können das beste für Ihre Bedürfnisse mit all diesen Hinweisen rund um;)

5

Oben zeigt ein sehr einfaches Stück Code, um Zufallszahlen zu generieren. Es ist ein Konsolenprogramm, das in C# geschrieben ist. Wenn Sie irgendeine grundlegende Programmierung kennen, sollte dies verständlich und leicht in jede andere gewünschte Sprache zu konvertieren sein.

Die DateTime nimmt einfach ein aktuelles Datum und eine aktuelle Uhrzeit auf, die meisten Programmiersprachen verfügen über eine Möglichkeit, dies zu tun.

Die Variablen Stunde, Minute, Sekunde und Millisekunde teilen den Datumswert in seine Bestandteile auf. Wir sind nur an diesen Teilen interessiert, können also den Tag ignorieren. In den meisten Sprachen werden Daten und Zeiten in der Regel als Strings dargestellt. In .Net haben wir Einrichtungen, mit denen wir diese Informationen leicht analysieren können. Aber in den meisten anderen Sprachen, in denen Zeiten als Zeichenfolgen dargestellt werden, ist es nicht allzu schwierig, die Zeichenfolge für die gewünschten Teile zu analysieren und sie in ihre Zahlen zu konvertieren. Diese Einrichtungen werden normalerweise sogar in den ältesten Sprachen angeboten.

Der Seed gibt uns im Wesentlichen eine Startnummer, die sich immer ändert. Traditionell würde man diese Zahl einfach mit einem Dezimalwert zwischen 0 und 1 multiplizieren, um diesen Schritt zu umgehen.

Der obere Bereich definiert den maximalen Wert. Die erzeugte Zahl wird nie über diesem Wert liegen. Auch wird es nie unter 0 sein. Also keine Mittel. Aber wenn Sie Negative möchten, können Sie es einfach manuell negieren. (Indem sie sie mit -1 multipliziert)

Die tatsächliche Variable randNumis was den Zufallswert hält Sie interessiert sind.

Der Trick ist, den Rest (das Modul) zu erhalten, nachdem die Samen durch den oberen Bereich geteilt wird. Der Rest wird immer kleiner sein als der Divisor, der in diesem Fall 100 ist. Einfache Mathematik sagt Ihnen, dass Sie keinen Rest größer als der Divisor haben können. Also, wenn Sie durch 10 dividieren, können Sie einen Rest größer als 10 haben. Es ist dieses einfache Gesetz, das uns unsere Zufallszahl zwischen 0 und 100 in diesem Fall bekommt.

Die console.writeline gibt es einfach auf dem Bildschirm aus.

Die console.readline pausiert einfach das Programm, so dass Sie es sehen können.

Dies ist ein sehr einfaches Stück Code, um Zufallszahlen zu generieren. Wenn Sie dieses Programm jeden Tag an genau demselben Intervil ausführen (aber Sie müssten es für die gleiche Stunde, Minute, Sekunde und Millisekunde tun), würden Sie mehr als einen Tag damit beginnen, die gleiche Menge von Zahlen immer wieder zu erzeugen zusätzlicher Tag. Dies liegt daran, dass es an die Zeit gebunden ist. Das ist die Auflösung des Generators. Wenn Sie also den Code dieses Programms und die Zeit, zu der es ausgeführt wird, kennen, können Sie die generierte Zahl vorhersagen, aber es wird nicht einfach sein. Deshalb habe ich Millisekunden gebraucht. Benutze Sekunden oder Minuten, um zu sehen, was ich meine. Man könnte also eine Tabelle schreiben, die zeigt, wenn 1 eingeht, 0 kommt heraus, wenn 2 eingeht, kommt 0 heraus und so weiter. Sie können dann die Ausgabe für jede Sekunde und den Bereich der erzeugten Zahlen vorhersagen. Je mehr Sie die Auflösung erhöhen (indem Sie die sich ändernden Zahlen erhöhen), desto schwieriger ist es und desto länger dauert es, ein vorhersagbares Muster zu erhalten. Diese Methode ist gut genug für die meisten Menschen.

Das ist die alte Art der Zufallszahlengenerierung für grundlegende Spiele. Es musste schnell und einfach sein. Es ist. Dies zeigt auch genau, warum Zufallszahlengeneratoren nicht wirklich zufällig, sondern pseudozufällig sind.

Ich hoffe, dies ist eine vernünftige Antwort auf Ihre Frage.

3

Die Mersenne twister hat einen sehr langen Zeitraum (2^19937-1).

Hier ist eine sehr einfache Implementierung in C++:

struct MT{ 
    unsigned int *mt, k, g; 
    ~MT(){ delete mt; } 
    MT(unsigned int seed) : mt(new unsigned int[624]), k(0), g(0){ 
     for (int i=0; i<624; i++) 
      mt[i]=!i?seed:(1812433253U*(mt[i-1]^(mt[i-1]>>30))+i); 
    } 
    unsigned int operator()(){ 
     unsigned int q=(mt[k]&0x80000000U)|(mt[(k+1)%624]&0x7fffffffU); 
     mt[k]=mt[(k+397)%624]^(q>>1)^((q&1)?0x9908b0dfU:0); 
     unsigned int y = mt[k]; 
     y ^= (y >> 11); 
     y ^= (y << 7) & 0x9d2c5680U; 
     y ^= (y << 15) & 0xefc60000U; 
     y ^= (y >> 18); 
     k = (k+1)%624; 
     return y; 
    } 
}; 
3

Eine gute Möglichkeit, um Zufallszahl zu erhalten, ist das Umgebungsgeräuschniveau zu überwachen kommt über das Mikrofon des Computers. Wenn Sie einen Treiber (oder eine Sprache, die die Mikrofoneingabe unterstützt) erhalten und diese in eine Zahl konvertieren können, sind Sie auf dem besten Weg!

Es wurde auch erforscht, wie man "wahre Zufälligkeit" erhält - da Computer nichts anderes als binäre Maschinen sind, können sie uns keine "wahre Zufälligkeit" geben. Nach einer Weile beginnt sich die Sequenz zu wiederholen. Die Suche nach einer besseren Zufallszahlengenerierung läuft noch, aber die Überwachung der Umgebungsgeräusche in einem Raum ist ein guter Weg, Musterbildung in Ihrer zufälligen Generation zu verhindern.

Sie können this wiki article für weitere Informationen über die Wissenschaft hinter Zufallsgenerierung nachschlagen.

1

Diese document ist eine sehr nette Zusammenfassung der Pseudozufallszahlengenerierung und hat eine Reihe von Routinen enthalten (in C). Es diskutiert auch die Notwendigkeit einer geeigneten Aussaat der Zufallszahlengeneratoren (siehe Regel 3). Besonders nützlich ist die Verwendung von/dev/randon/(wenn Sie auf einem Linux-Rechner arbeiten).

Hinweis: Die Routinen in diesem Dokument sind viel einfacher zu codieren als der Mersenne Twister. Siehe auch den WELLRNG Generator, der bessere theoretische Eigenschaften haben soll, als Alternative zum MT.

1

Lesen Sie das Rands Buch von Zufallszahlen (Monte Carlo Buch von Zufallszahlen) die Zahlen darin sind zufällig für Sie generiert !!! Mein Großvater hat für Rand gearbeitet.

2

Wenn Sie nach einer theoretischen Behandlung von Zufallszahlen suchen, können Sie wahrscheinlich einen Blick auf Band 2 der Die Kunst der Computerprogrammierung. Es hat ein Kapitel für Zufallszahlen gewidmet. Schau, ob es dir hilft.

1

Die meisten RNGs (Zufallsgeneratoren) benötigen ein wenig Initialisierung. Dies ist normalerweise der Fall, um eine Seeding-Operation durchzuführen und die Ergebnisse der gesetzten Werte für die spätere Verwendung zu speichern. Hier ist ein Beispiel für ein Impfverfahren von einem randomizer ich für ein Spiel-Engine geschrieben:

/// <summary> 
    /// Initializes the number array from a seed provided by <paramref name="seed">seed</paramref>. 
    /// </summary> 
    /// <param name="seed">Unsigned integer value used to seed the number array.</param> 
    private void Initialize(uint seed) 
    { 
     this.randBuf[0] = seed; 
     for (uint i = 1; i < 100; i++) 
     { 
      this.randBuf[i] = (uint)(this.randBuf[i - 1] >> 1) + i; 
     } 
    } 

Dies wird vom Konstruktor der Randomisierung Klasse aufgerufen. Nun können die echten Zufallszahlen unter Verwendung der oben genannten gesetzten Werte gewürfelt/berechnet werden. Dies ist normalerweise der Fall, in dem der tatsächliche Randomisierungsalgorithmus angewendet wird. Hier ist ein weiteres Beispiel:

/// <summary> 
    /// Refreshes the list of values in the random number array. 
    /// </summary> 
    private void Roll() 
    { 
     for (uint i = 0; i < 99; i++) 
     { 
      uint y = this.randBuf[i + 1] * 3794U; 
      this.randBuf[i] = (((y >> 10) + this.randBuf[i])^this.randBuf[(i + 399) % 100]) + i; 
      if ((this.randBuf[i] % 2) == 1) 
      { 
       this.randBuf[i] = (this.randBuf[i + 1] << 21)^(this.randBuf[i + 1] * (this.randBuf[i + 1] & 30)); 
      } 
     } 
    } 

nun die gewalzten Werte für die spätere Verwendung in diesem Beispiel gespeichert sind, aber diese Zahlen können auch im laufenden Betrieb berechnet werden. Der Vorteil der Vorberechnung ist eine leichte Leistungssteigerung. Abhängig vom verwendeten Algorithmus können die gerollten Werte direkt zurückgegeben werden oder einige Last-Minute-Berechnungen durchlaufen, wenn sie vom Code angefordert werden. Hier ist ein Beispiel, das aus den vorgerollt Werte annimmt und spuckt eine sehr gut aussehende Pseudo-Zufallszahl:

/// <summary> 
    /// Retrieves a value from the random number array. 
    /// </summary> 
    /// <returns>A randomly generated unsigned integer</returns> 
    private uint Random() 
    { 
     if (this.index == 0) 
     { 
      this.Roll(); 
     } 

     uint y = this.randBuf[this.index]; 
     y = y^(y >> 11); 
     y = y^((y << 7) + 3794); 
     y = y^((y << 15) + 815); 
     y = y^(y >> 18); 
     this.index = (this.index + 1) % 100; 
     return y; 
    } 
2

Wenn Sie wollen, sind manuell, harte Code, Ihren eigenen Zufallsgenerator kann ich Ihnen nicht geben Effizienz, Ich kann Ihnen jedoch Zuverlässigkeit geben. Ich entschied mich tatsächlich dafür, etwas Code zu schreiben, um die Verarbeitungsgeschwindigkeit eines Computers zu testen, indem ich rechtzeitig zählte, und das brachte mich dazu, meinen eigenen Zufallszahlengenerator mit dem Zählalgorithmus für Modulo zu schreiben (die Zählung ist zufällig). Versuchen Sie es bitte selbst und testen Sie die Anzahlverteilung in einem großen Test-Set. Das ist übrigens in Python geschrieben.

def count_in_time(n): 
    import time 
    count = 0 
    start_time = time.clock() 
    end_time = start_time + n 
    while start_time < end_time: 
     count += 1 
     start_time += (time.clock() - start_time) 
    return count 


def generate_random(time_to_count, range_nums, rand_lst_size): 
    randoms = [] 
    iterables = range(range_nums) 
    count = 0 
    for i in range(rand_lst_size): 
     count += count_in_time(time_to_count) 
     randoms.append(iterables[count%len(iterables)]) 
    return randoms 
Verwandte Themen