In diesem Kapitel werden zunächst verschiedene Möglichkeiten erläutert, um Java -Zufallszahlen zu generieren, und demonstriert sie dann anhand von Beispielen.
Überblick:
Wirst du hier sagen, was ist die Schwierigkeit, Zufallszahlen zu generieren? Ist es nicht nur, Java eingekapselt zu verwenden? Natürlich ist es im Allgemeinen in Ordnung, und die in diesem Artikel zu erläuterten Algorithmen basieren auch auf dieser zufälligen Bibliotheksfunktion.
Dieser Artikel konzentriert sich hauptsächlich auf das Verhalten der Stichprobe, und die Stichprobe selbst hat eine implizite Regel, die keine doppelten Daten haben soll. Ok, mit diesen Anweisungen. Sie können zunächst versuchen, einige Ihrer eigenen Ideen zu verwenden, um zufällige Zahlen ohne wiederholte Generation zu generieren.
Algorithmusversuche:
Einige gute Algorithmen erscheinen oft begleitet von einigen nicht so guten Algorithmen. Für Algorithmen, die nicht sehr effektiv sind, haben sie im Allgemeinen ein gemeinsames Merkmal, das leicht zu verstehen und implementiert ist. Das Folgende ist eine kurze Erklärung durch einen Schritt-für-Schritt-Ansatz.
Ersten Versuch: naiver Zufallsalgorithmus
Dieser Algorithmus ist leicht zu verstehen, er ist zufällig! Jedes Mal, wenn eine Zufallszahl generiert und zum Satz hinzugefügt wird.
private void einfacher und int start, int End, int count) {System.out.println ("Natural Random Algorithmus:"); StringBuffer Buffer = new StringBuffer (); für (int i = 0; i <count; i ++) {int random = numberUnutils.randomintier (Start, Ende); buffer.Append (i == 0? ("[" + random): ("," + random)); } buffer.append ("]"); System.out.println (Buffer); } Der zweite Versuch: Überprüfen Sie den existenziellen Zufallsalgorithmus
Wir wissen, dass es ein Problem mit der obigen Methode gibt, dh es kann doppelte Daten geben. Wir haben also überprüft, ob die Zahl bereits bei der Erzeugung einer Zufallszahl existiert, und wenn sie existiert, wird sie regeneriert.
private void checkrandom (int start, int End, int count) {System.out.println ("Existentius Random Algorithm:"); StringBuffer Buffer = new StringBuffer (); List <Ganzzahl> save = new ArrayList <> (); für (int i = 0; i <count; i ++) {int random = numberUnutils.randomintier (Start, Ende); if (exits (save, random)) {i--; weitermachen; } save.add (random); buffer.Append (i == 0? ("[" + random): ("," + random)); } buffer.append ("]"); System.out.println (Buffer); } Der dritte Versuch: Elemententfernung zufälliger Algorithmus
Der obige Algorithmus hat das Problem der Datenverdoppelung gelöst. Ein sehr schlechtes Problem ist jedoch, dass es uns möglicherweise lange dauern kann, bis Stichproben -Zufallszahlen generiert werden (dies hängt vom Gesicht ab ...).
Hier haben wir jedoch neue Ideen. Das soll zufällig eine Zahl in einem Satz verwenden und sie entfernen, wenn dies ausgewählt ist. Dann erreichen Sie diese Zahl dann nicht zufällig wieder, wenn sie zufällig ist? Dies löst das Problem der Wiederholung von Zufallszahlen sehr gut. Der Code ist wie folgt:
private void removerandom (int start, int End, int count) {System.out.println ("Elemententfernung zufälliger Algorithmus:"); StringBuffer Buffer = new StringBuffer (); Liste <Ganzzahl> numbers = initList (start, Ende); für (int i = 0; i <count; i ++) {int random = numberUnutils.randomintier (count - i); Buffer.Append (i == 0? ("[" + number.get (zufällig)): ("," + number.get (zufällig)); numbers.remove (zufällig); } buffer.append ("]"); System.out.println (Buffer); } Viertes Versuch: Zufallsalgorithmus übertragen von Zustandsübertragung
In vielen meiner früheren Blogs sind einige staatliche Transferprozesse in Algorithmen. Die Staatsübertragung ist auch einer meiner Lieblingsalgorithmen. Abbildung 1 markiert den Wertbereich der Zufallszahlen, und die Orangenzahl in der Sequenz ist die zufällige Sequenz im Ergebnis. Es gibt einige gepunktete Pfeile in der unteren Sequenz, die den Zustandsübergang darstellen.
Abbildung 1 Stichprobenerzeugungsalgorithmus für Zufallszahlenerzeugung basierend auf dem Zustandsübergang
Implementierungscode:
private void statusrandom (int start, int end, int count) {System.out.println ("Statustransfer Zufallsalgorithmus:"); StringBuffer Buffer = new StringBuffer (); int [] status = new int [Ende + 1]; für (int i = 0; i <count; i ++) {int random = numberUnutils.randomintier (Start, Ende); System.err.println (zufällig); if (status [random] == 0) {buffer.Append (i == 0? ("[" + random): ("," + random)); Status [Random] = Random == Ende? Start: (zufällig + 1); // Es ist unmöglich, vor Start eine Nummer zu haben} else {// Statustransfer int index = random; do {index = status [index]; } while (Status [Index]! = 0); buffer.Append (i == 0? ("[" + index): ("," + index)); Status [index] = index == Ende? Start: (Index + 1); // Es ist unmöglich, vor Start eine Nummer zu haben}} buffer.append ("]"); System.out.println (Buffer); } Der fünfte Versuch: Rekursive Floyd -Zufallsalgorithmus
Der Floyd -Algorithmus ist letztendlich ein staatlicher Übertragungsprozess. Der Algorithmus benötigt eine Liste oder ein Array, um die bestimmte Zufallszahl zu speichern. Wie der Name schon sagt, werde ich hier rekursive Lösungen verwenden. Bei der Rekursion übertragen wir den Zustand der I-Th-Zufallszahl auf die I-1-Zufallszahl. Der Code ist wie folgt:
private list <GanzEger> SimpleFloyd (Liste <Integer> Liste, int count, int start, int end) {if (count == 0) {returnlist; } list = SimpleFloyd (Liste, Graf - 1, Start, Ende - 1); int random = numberUnutils.randintEger (Start, Ende); if (list.contains (zufällig)) {list.add (Ende); } else {list.add (random); } Rückgabeliste; } Sechster Versuch: Iterieren Sie über Floyd Random Algorithmus
Die Idee ähnelt dem rekursiven Floyd -zufälligen Algorithmus oben, aber hier fügen wir eine Variable hinzu, um sie zu optimieren. Es besteht keine Notwendigkeit, wieder aufzunehmen. Der Code ist wie folgt:
private list <GeNeger> itererationFloyd (int start, int End, int count) {System.out.println ("Iterativer Floyd -Zufallsalgorithmus:"); List <Ganzzahl> list = new ArrayList <> (); für (int i = end - count+1; i <end; i ++) {int random = numberUtils.randomintier (start, i); if (list.contains (zufällig)) {list.add (i); } else {list.add (random); }} Rückgabeliste; } Testergebnisse:
Abbildung 2 Zufallszahlengenerierung Algorithmus-Testergebnisse
In den obigen Testergebnissen können wir deutlich erkennen, dass der naive Zufallsalgorithmus nicht nur doppelte Daten hat, sondern auch die zeitaufwändigste ist. Vermeiden Sie daher die Verwendung dieses Algorithmus bei der Erzeugung von Stichproben -Zufallszahlen. Unter den letzteren Algorithmen ist der zufällige Algorithmus der Zustandsübertragung der beste, und der iterative Floyd -Zufallsalgorithmus ist zweiter. Dies kann nach persönlichen Vorlieben erfolgen.