Ich muss innerhalb eines bestimmten Intervalls [max; min] Zufallszahlen generieren.
Außerdem sollten die Zufallszahlen gleichmäßig über das Intervall verteilt sein und sich nicht an einem bestimmten Punkt befinden.
Derzeit generiere ich als:
for(int i=0; i<6; i++)
{
DWORD random = rand()%(max-min+1) + min;
}
Aus meinen Tests werden Zufallszahlen nur um einen Punkt generiert.
Example
min = 3604607;
max = 7654607;
Zufallszahlen generiert:
3631594
3609293
3630000
3628441
3636376
3621404
Aus den Antworten unten: OK, RAND_MAX ist 32767. Ich bin auf einer C ++ Windows-Plattform. Gibt es eine andere Methode, um Zufallszahlen mit einer gleichmäßigen Verteilung zu generieren?
rand()
einheitlich ist. Welche Bibliothek benutzt du?cstdlib.h
'srand()
ist NICHT einheitlich: cplusplus.com/reference/cstdlib/randAntworten:
Warum
rand
ist eine schlechte IdeeDie meisten Antworten, die Sie hier erhalten haben, verwenden die
rand
Funktion und den Moduloperator. Diese Methode generiert möglicherweise keine einheitlichen Zahlen (dies hängt vom Bereich und dem Wert von abRAND_MAX
) und wird daher nicht empfohlen.C ++ 11 und Generierung über einen Bereich
Mit C ++ 11 sind mehrere andere Optionen gestiegen. Eine davon entspricht Ihren Anforderungen, um eine Zufallszahl in einem Bereich zu generieren
std::uniform_int_distribution
. Hier ist ein Beispiel:Und hier ist das laufende Beispiel.
Andere Zufallsgeneratoren
Der
<random>
Header bietet unzählige andere Zufallszahlengeneratoren mit unterschiedlichen Verteilungen, einschließlich Bernoulli, Poisson und Normal.Wie kann ich einen Container mischen?
Der Standard sieht vor
std::shuffle
, dass wie folgt verwendet werden kann:Der Algorithmus ordnet die Elemente zufällig mit einer linearen Komplexität neu.
Boost.Random
Eine andere Alternative, falls Sie keinen Zugriff auf einen C ++ 11 + -Compiler haben, ist die Verwendung von Boost.Random . Die Benutzeroberfläche ist der von C ++ 11 sehr ähnlich.
quelle
mt19937
Typ?1 9 6 2 8 7 1 4 7 7
. Wie können Sie dies jedes Mal randomisieren, wenn wir das Programm ausführen?[Bearbeiten] Warnung: Nicht
rand()
für Statistiken, Simulationen, Kryptografie oder andere schwerwiegende Zwecke verwenden .Es ist gut genug, um Zahlen für einen typischen Menschen in Eile zufällig aussehen zu lassen , nicht mehr.
Siehe @ Jefffreys Antwort für bessere Optionen oder diese Antwort für kryptosichere Zufallszahlen.
Im Allgemeinen zeigen die hohen Bits eine bessere Verteilung als die niedrigen Bits. Daher wird empfohlen, Zufallszahlen eines Bereichs für einfache Zwecke zu generieren:
Hinweis : Stellen Sie sicher, dass RAND_MAX + 1 nicht überläuft (danke Demi)!
Die Division erzeugt eine Zufallszahl im Intervall [0, 1); "dehnen" Sie dies auf den gewünschten Bereich. Nur wenn sich max-min + 1 RAND_MAX nähert, benötigen Sie eine "BigRand ()" - Funktion, wie sie von Mark Ransom veröffentlicht wurde.
Dies vermeidet auch einige Schnittprobleme aufgrund des Modulos, die Ihre Zahlen noch weiter verschlechtern können.
Es ist nicht garantiert, dass der eingebaute Zufallszahlengenerator die für statistische Simulationen erforderliche Qualität aufweist. Es ist in Ordnung, dass Zahlen für einen Menschen "zufällig" aussehen, aber für eine ernsthafte Anwendung sollten Sie etwas Besseres nehmen - oder zumindest seine Eigenschaften überprüfen (eine gleichmäßige Verteilung ist normalerweise gut, aber die Werte korrelieren tendenziell und die Reihenfolge ist deterministisch ). Knuth hat eine ausgezeichnete (wenn auch schwer zu lesende) Abhandlung über Zufallszahlengeneratoren, und ich fand kürzlich, dass LFSR ausgezeichnet und verdammt einfach zu implementieren ist, da seine Eigenschaften für Sie in Ordnung sind.
quelle
( rand() / ((double)RAND_MAX+1)) * (max-min+1) + min
Verschieben Sie die Konvertierung einfach auf doppelt und vermeiden Sie das Problem.Ich möchte die hervorragenden Antworten von Angry Shoe und Peterchen mit einem kurzen Überblick über den Stand der Technik im Jahr 2015 ergänzen:
Einige gute Entscheidungen
randutils
Die
randutils
Bibliothek (Präsentation) ist eine interessante Neuheit, die eine einfache Oberfläche und (deklarierte) robuste Zufallsfunktionen bietet. Es hat die Nachteile, dass es eine Abhängigkeit von Ihrem Projekt hinzufügt, und da es neu ist, wurde es nicht ausführlich getestet. Da ich kostenlos (MIT-Lizenz) und nur als Header bin, denke ich, dass es einen Versuch wert ist.Minimale Probe: ein Würfelwurf
Auch wenn man sich nicht für die Bibliothek interessiert, bietet die Website ( http://www.pcg-random.org/ ) viele interessante Artikel zum Thema Zufallszahlengenerierung im Allgemeinen und zur C ++ - Bibliothek im Besonderen.
Boost.Random
Boost.Random
(Dokumentation) ist die Bibliothek , die inspiriertC++11
s‘<random>
, mit denen Aktien viel von der Schnittstelle. Während es theoretisch auch eine externe Abhängigkeit ist,Boost
hat es mittlerweile den Status einer "Quasi-Standard" -Bibliothek, und seinRandom
Modul könnte als die klassische Wahl für die Erzeugung von Zufallszahlen guter Qualität angesehen werden. Es bietet zwei Vorteile in Bezug auf dieC++11
Lösung:random_device
verwendet systemspezifische Methoden, um eine Aussaat von guter Qualität zu ermöglichenDer einzige kleine Fehler ist, dass das Modulangebot
random_device
nicht nur Header ist, sondern kompiliert und verknüpft werden mussboost_random
.Minimale Probe: ein Würfelwurf
Während die minimale Stichprobe gut funktioniert, sollten echte Programme zwei Verbesserungen verwenden:
mt19937
athread_local
: Der Generator ist ziemlich prall (> 2 KB) und wird besser nicht auf dem Stapel zugeordnetmt19937
mit mehr als einer ganzen Zahl: Der Mersenne Twister hat einen großen Zustand und kann während der Initialisierung von mehr Entropie profitierenEinige nicht so gute Entscheidungen
Die C ++ 11-Bibliothek
Die
<random>
Bibliothek ist zwar die idiomatischste Lösung, bietet aber nicht viel im Austausch für die Komplexität ihrer Schnittstelle, selbst für die Grundbedürfnisse. Der Fehler liegt darin, dassstd::random_device
der Standard keine minimale Qualität für seine Ausgabe vorschreibt (solangeentropy()
zurückgegeben wird0
), und ab 2015 druckt MinGW (nicht der am häufigsten verwendete Compiler, aber kaum eine esoterische Wahl) immer4
auf dem minimalen Sample.Minimale Probe: ein Würfelwurf
Wenn die Implementierung nicht schlecht ist, sollte diese Lösung der Boost-Lösung entsprechen, und es gelten dieselben Vorschläge.
Godots Lösung
Minimale Probe: ein Würfelwurf
Dies ist eine einfache, effektive und saubere Lösung. Nur ein Fehler, die Kompilierung wird eine Weile dauern - ungefähr zwei Jahre, vorausgesetzt, C ++ 17 wird rechtzeitig veröffentlicht und die experimentelle
randint
Funktion wird in den neuen Standard aufgenommen. Vielleicht verbessern sich bis dahin auch die Garantien für die Aussaatqualität.Die schlechter-ist-besser- Lösung
Minimale Probe: ein Würfelwurf
Die alte C-Lösung wird aus guten Gründen als schädlich angesehen (siehe die anderen Antworten hier oder diese detaillierte Analyse ). Dennoch hat es seine Vorteile: Es ist einfach, tragbar, schnell und ehrlich, in dem Sinne, dass bekannt ist, dass die Zufallszahlen, die man erhält, kaum anständig sind und man daher nicht versucht ist, sie für ernsthafte Zwecke zu verwenden.
Die Buchhaltungstrollösung
Minimale Probe: ein Würfelwurf
Während 9 ein etwas ungewöhnliches Ergebnis für einen normalen Würfelwurf ist, muss man die hervorragende Kombination guter Eigenschaften in dieser Lösung bewundern, die es schafft, die schnellste, einfachste, cachefreundlichste und tragbarste zu sein. Wenn man 9 durch 4 ersetzt, erhält man einen perfekten Generator für jede Art von Dungeons and Dragons-Würfel, wobei die symbolbeladenen Werte 1, 2 und 3 vermieden werden. Der einzige kleine Fehler ist, dass aufgrund der schlechten Laune von Dilberts Buchhaltungstrollen Dieses Programm erzeugt tatsächlich undefiniertes Verhalten.
quelle
randutils
Bibliothek heißt jetzt PCG.Wenn
RAND_MAX
32767 ist, können Sie die Anzahl der Bits leicht verdoppeln.quelle
rand
Anruf zurückkehrt0x1234
und der zweite0x5678
, erhalten Sie0x12345678
. Dies ist die einzige Nummer, mit der Sie beginnen können0x1234
, da die nächste Nummer immer sein wird0x5678
. Sie erhalten 32-Bit-Ergebnisse, haben aber nur 32768 mögliche Zahlen.Wenn Sie in der Lage sind, verwenden Sie Boost . Ich hatte viel Glück mit ihrer zufälligen Bibliothek .
uniform_int
sollte tun was du willst.quelle
uniform_int
damals. Es ist ziemlich einfach, eine unvoreingenommene Ausgabe zu generieren. Hier gab es mehrere Fragen, die die Methode demonstrieren.Wenn Sie sich Gedanken über Zufälligkeit und nicht über Geschwindigkeit machen, sollten Sie eine sichere Methode zur Generierung von Zufallszahlen verwenden. Es gibt verschiedene Möglichkeiten, dies zu tun ... Die einfachste ist die Verwendung des Zufallszahlengenerators von OpenSSL .
Sie können auch Ihre eigenen mit einem Verschlüsselungsalgorithmus (wie AES ) schreiben . Durch Auswahl eines Seeds und einer IV und anschließende kontinuierliche Verschlüsselung der Ausgabe der Verschlüsselungsfunktion. Die Verwendung von OpenSSL ist einfacher, aber weniger männlich.
quelle
Sie sollten nach
RAND_MAX
Ihrem speziellen Compiler / Ihrer Umgebung suchen . Ich denke, Sie würden diese Ergebnisse sehen, wenn Sierand()
eine zufällige 16-Bit-Zahl erzeugen. (Sie scheinen davon auszugehen, dass es sich um eine 32-Bit-Zahl handelt).Ich kann nicht versprechen, dass dies die Antwort ist, aber bitte geben Sie Ihren Wert
RAND_MAX
und ein wenig mehr Details zu Ihrer Umgebung an.quelle
Überprüfen Sie, was
RAND_MAX
sich auf Ihrem System befindet - ich vermute, es sind nur 16 Bit, und Ihre Reichweite ist zu groß dafür.Darüber hinaus finden Sie in dieser Diskussion Folgendes : Generieren zufälliger Ganzzahlen innerhalb eines gewünschten Bereichs und Hinweise zur Verwendung (oder nicht) der Funktion C rand () .
quelle
Dies ist nicht der Code, aber diese Logik kann Ihnen helfen.
quelle
Wenn Sie möchten, dass die Zahlen gleichmäßig über den Bereich verteilt sind, sollten Sie Ihren Bereich in mehrere gleiche Abschnitte aufteilen, die die Anzahl der benötigten Punkte darstellen. Dann erhalten Sie eine Zufallszahl mit einem Min / Max für jeden Abschnitt.
Als weitere Anmerkung sollten Sie wahrscheinlich nicht verwenden,
rand()
da es nicht sehr gut ist, Zufallszahlen zu generieren. Ich weiß nicht, auf welcher Plattform Sie laufen, aber es gibt wahrscheinlich eine bessere Funktion, die Sie aufrufen könnenrandom()
.quelle
Dies sollte eine gleichmäßige Verteilung über den Bereich
[low, high)
ohne Verwendung von Floats ermöglichen, solange der Gesamtbereich kleiner als RAND_MAX ist.und für Werte größer als RAND_MAX möchten Sie so etwas wie
Dies ist ungefähr die Vorgehensweise von std :: uniform_int_distribution.
quelle
Eine kleine Stichprobe von Zufallszahlen muss naturgemäß nicht gleichmäßig verteilt sein. Sie sind schließlich zufällig. Ich bin damit einverstanden, dass, wenn ein Zufallszahlengenerator Zahlen generiert, die konsistent gruppiert zu sein scheinen, wahrscheinlich etwas nicht stimmt.
Aber denken Sie daran, dass Zufälligkeit nicht unbedingt einheitlich ist.
Bearbeiten: Ich habe "kleine Probe" hinzugefügt, um dies zu verdeutlichen.
quelle
Die von Mann 3 Rand gegebene Lösung für eine Zahl zwischen 1 und einschließlich 10 lautet:
In Ihrem Fall wäre es:
Natürlich ist dies keine perfekte Zufälligkeit oder Einheitlichkeit, wie einige andere Nachrichten hervorheben, aber dies reicht für die meisten Fälle aus.
quelle
@Lösung
((double) rand() / (RAND_MAX+1)) * (max-min+1) + min
Warnung : Vergessen Sie nicht, dass Sie aufgrund von Dehnungen und möglichen Präzisionsfehlern (selbst wenn RAND_MAX groß genug wäre) nur gleichmäßig verteilte "Bins" und nicht alle Zahlen in [min, max] generieren können.
@ Lösung: Bigrand
Warnung : Beachten Sie, dass dies die Bits verdoppelt, aber im Allgemeinen immer noch nicht alle Zahlen in Ihrem Bereich generieren kann, dh es ist nicht unbedingt richtig, dass BigRand () alle Zahlen in seinem Bereich generiert.
Info : Ihr Ansatz (Modulo) ist "in Ordnung", solange der Bereich von rand () Ihren Intervallbereich überschreitet und rand () "einheitlich" ist. Der Fehler für höchstens die ersten max - min Zahlen ist 1 / (RAND_MAX +1).
Außerdem schlage ich vor, auch in C ++ 11 auf das neue Zufallspaket e umzusteigen, das bessere und vielfältigere Implementierungen bietet als rand ().
quelle
Dies ist die Lösung, die ich mir ausgedacht habe:
Dies ist eine Bucket-Lösung, die konzeptionell den Lösungen ähnelt,
rand() / RAND_MAX
mit denen ein Gleitkommabereich zwischen 0 und 1 ermittelt und dann in einen Bucket gerundet wird. Es wird jedoch eine rein ganzzahlige Mathematik verwendet und der ganzzahlige Teilungsboden verwendet, um den Wert auf den nächsten Bucket abzurunden.Es werden einige Annahmen getroffen. Erstens wird davon ausgegangen, dass dies
RAND_MAX * (max - min + 1)
immer in eine passtint32_t
. WennRAND_MAX
32767 und 32-Bit-Int-Berechnungen verwendet werden, können Sie maximal 32767 verwenden. Wenn Ihre Implementierung einen viel größeren RAND_MAX hat, können Sie dies überwinden, indem Sie eine größere Ganzzahl (wieint64_t
) für die Berechnung verwenden. Zweitens, wenn verwendetint64_t
wird, aberRAND_MAX
immer noch 32767 ist, werden in Bereichen, die größer sind alsRAND_MAX
Sie, "Löcher" in den möglichen Ausgangsnummern bekommen. Dies ist wahrscheinlich das größte Problem bei Lösungen, die aus der Skalierung abgeleitet werdenrand()
.Das Testen über eine große Anzahl von Iterationen zeigt jedoch, dass diese Methode für kleine Bereiche sehr einheitlich ist. Es ist jedoch möglich (und wahrscheinlich), dass dies mathematisch gesehen eine geringe Verzerrung aufweist und möglicherweise Probleme entwickelt, wenn sich der Bereich nähert
RAND_MAX
. Testen Sie es selbst und entscheiden Sie, ob es Ihren Anforderungen entspricht.quelle
Natürlich gibt Ihnen der folgende Code keine Zufallszahlen, sondern Pseudozufallszahlen. Verwenden Sie den folgenden Code
Beispielsweise:
Sie müssen anrufen
Andernfalls sind die Zahlen nicht nahezu zufällig.
quelle
Ich habe das gerade im Internet gefunden. Das sollte funktionieren:
quelle