Ich habe versucht, zu verwenden random.randint(0, 100)
, aber einige Zahlen waren die gleichen. Gibt es eine Methode / ein Modul zum Erstellen einer Liste eindeutiger Zufallszahlen?
Hinweis: Der folgende Code basiert auf einer Antwort und wurde hinzugefügt, nachdem die Antwort veröffentlicht wurde. Es ist kein Teil der Frage; Es ist die Lösung.
def getScores():
# open files to read and write
f1 = open("page.txt", "r");
p1 = open("pgRes.txt", "a");
gScores = [];
bScores = [];
yScores = [];
# run 50 tests of 40 random queries to implement "bootstrapping" method
for i in range(50):
# get 40 random queries from the 50
lines = random.sample(f1.readlines(), 40);
Antworten:
Dies gibt eine Liste von 10 Zahlen zurück, die aus dem Bereich 0 bis 99 ohne Duplikate ausgewählt wurden.
In Bezug auf Ihr spezifisches Codebeispiel möchten Sie wahrscheinlich alle Zeilen aus der Datei einmal lesen und dann zufällige Zeilen aus der gespeicherten Liste im Speicher auswählen. Beispielsweise:
Auf diese Weise müssen Sie vor Ihrer Schleife nur einmal aus der Datei lesen. Dies ist viel effizienter, als zum Anfang der Datei zurückzukehren und
f1.readlines()
bei jeder Schleifeniteration erneut aufzurufen .quelle
Sie können die Verwendung Shuffle - Funktion aus dem Zufalls Modul wie folgt aus :
Beachten Sie hier, dass die Shuffle-Methode keine erwartete Liste zurückgibt, sondern nur die als Referenz übergebene Liste mischt.
quelle
Sie können zunächst eine Liste von Zahlen von erstellen
a
zub
, woa
undb
sind jeweils die kleinsten und größten Zahlen in Ihrer Liste, mische es dann mit Fisher-Yates - Algorithmus oder der Python mitrandom.shuffle
Methode.quelle
Die in dieser Antwort vorgestellte Lösung funktioniert, kann jedoch mit dem Speicher problematisch werden, wenn die Stichprobengröße klein ist, die Population jedoch groß ist (z
random.sample(insanelyLargeNumber, 10)
. ).Um das zu beheben, würde ich folgendes tun:
quelle
random.sample
Verwendet diesen Ansatz jetzt für eine kleine Anzahl von Stichproben aus einer großen Population, sodass dieses Problem mit dem Speicher nicht mehr wirklich besteht. Obwohl zu dem Zeitpunkt, als diese Antwort geschrieben wurde, die Implementierung vonrandom.shuffle
möglicherweise anders war.Linearer kongruenter Pseudozufallszahlengenerator
Dieses Problem kann mit einem einfachen linearen Kongruenzgenerator gelöst werden . Dies erfordert einen konstanten Speicheraufwand (8 Ganzzahlen) und höchstens 2 * (Sequenzlänge) Berechnungen.
Alle anderen Lösungen verbrauchen mehr Speicher und mehr Rechenleistung! Wenn Sie nur wenige zufällige Sequenzen benötigen, ist diese Methode erheblich günstiger.
N
Wenn Sie für Größenbereiche in der Größenordnung vonN
eindeutigenk
Sequenzen oder mehr generieren möchten , empfehle ich die akzeptierte Lösung mit den integrierten Methoden,random.sample(range(N),k)
da diese optimiert wurde in Python auf Geschwindigkeit wurde.Code
Verwendung
Die Verwendung dieser Funktion "random_range" ist die gleiche wie für jeden Generator (wie "range"). Ein Beispiel:
Probenergebnisse
quelle
prime
, gibt die Funktion nur 4 mögliche Antworten zurück, da diesvalue
die einzige zufällig ausgewählte Sache mit 4 möglichen Werten ist, wenn wir mindestens (4 wählen 2) = benötigen 6, (unter Berücksichtigung einer nicht zufälligen Reihenfolge).random_range(2,4)
gibt Werte {(1, 0), (3, 2), (2, 1), (0, 3)} zurück, aber niemals das Paar (3,1) (oder (1,3)). Erwarten Sie bei jedem Funktionsaufruf neue zufällig generierte große Primzahlen?random_range(v)
siev
stattdessen zu eindeutigen Sequenzen zurückkehrenv!
)Wenn die Liste von N Zahlen von 1 bis N zufällig generiert wird, besteht die Möglichkeit, dass einige Zahlen wiederholt werden.
Wenn Sie eine Liste von Zahlen von 1 bis N in zufälliger Reihenfolge wünschen, füllen Sie ein Array mit ganzen Zahlen von 1 bis N und verwenden Sie dann ein Fisher-Yates-Shuffle oder Pythons
random.shuffle()
.quelle
Wenn Sie extrem große Zahlen abtasten müssen, können Sie diese nicht verwenden
range
weil es wirft:
Wenn
random.sample
die Anzahl der gewünschten Artikel aufgrund des zu kleinen Bereichs nicht erreicht werden kannes wirft:
Diese Funktion löst beide Probleme:
Verwendung mit extrem großen Stückzahlen:
Beispielergebnis:
Verwendung, wenn der Bereich kleiner als die Anzahl der angeforderten Artikel ist:
Beispielergebnis:
Es funktioniert auch mit negativen Bereichen und Schritten:
Beispielergebnisse:
quelle
Sie können Numpy verwenden Bibliothek für eine schnelle Antwort verwenden, wie unten gezeigt -
Das angegebene Code-Snippet listet 6 eindeutige Zahlen im Bereich von 0 bis 5 auf. Sie können die Parameter für Ihren Komfort anpassen.
Ausgabe
Es gibt keine Einschränkungen, wie wir in random.sample sehen, wie hier beschrieben .
Hoffe das hilft ein bisschen.
quelle
Die hier gegebene Antwort funktioniert sowohl in Bezug auf Zeit als auch auf Speicher sehr gut, ist jedoch etwas komplizierter, da fortgeschrittene Python-Konstrukte wie Yield verwendet werden. Die einfachere Antwort funktioniert in der Praxis gut, aber das Problem bei dieser Antwort ist, dass sie viele falsche Ganzzahlen erzeugen kann, bevor die erforderliche Menge tatsächlich erstellt wird. Probieren Sie es mit populationsSize = 1000, sampleSize = 999 aus. Theoretisch besteht die Möglichkeit, dass es nicht beendet wird.
Die folgende Antwort befasst sich mit beiden Fragen, da sie deterministisch und etwas effizient ist, derzeit jedoch nicht so effizient wie die beiden anderen.
wo die Funktionen getElem, percolateUp sind wie unten definiert
Schließlich betrug das Timing im Durchschnitt etwa 15 ms für einen großen Wert von n, wie unten gezeigt.
quelle
random.randint
Funktion 3996 mal auf, während die andere cca. 6000 mal. Keine so große Verbesserung, oder?Um ein Programm zu erhalten, das eine Liste von Zufallswerten ohne Duplikate generiert, die deterministisch, effizient und mit grundlegenden Programmierkonstrukten erstellt ist, berücksichtigen Sie die
extractSamples
unten definierte Funktion :Die Grundidee besteht darin, Intervalle
intervalLst
für mögliche Werte zu verfolgen , aus denen unsere erforderlichen Elemente ausgewählt werden können. Dies ist insofern deterministisch, als wir garantiert eine Stichprobe innerhalb einer festgelegten Anzahl von Schritten erzeugen (ausschließlich abhängig vonpopulationSize
undsampleSize
) .Um die obige Funktion zum Generieren unserer erforderlichen Liste zu verwenden,
Wir können auch mit einer früheren Lösung vergleichen (für einen niedrigeren Wert von populationsgröße)
Beachten Sie, dass ich den
populationSize
Wert reduziert habe , da bei Verwendung derrandom.sample
Lösung ein Speicherfehler für höhere Werte auftritt (auch in den vorherigen Antworten hier und hier erwähnt ). Bei den oben genannten Werten können wir auch beobachten, dassextractSamples
derrandom.sample
Ansatz übertroffen wird .PS: Obwohl der Kernansatz meiner früheren Antwort ähnlich ist , gibt es wesentliche Änderungen in der Implementierung sowie im Ansatz sowie eine Verbesserung der Klarheit.
quelle
Eine sehr einfache Funktion, die auch Ihr Problem löst
quelle
Das Problem bei den satzbasierten Ansätzen ("Wenn zufällige Werte in Rückgabewerten erneut versucht werden") besteht darin, dass ihre Laufzeit aufgrund von Kollisionen (die eine weitere Wiederholung "erneut versuchen" erfordern) unbestimmt ist, insbesondere wenn eine große Anzahl zufälliger Werte zurückgegeben wird aus dem Bereich.
Eine Alternative, die für diese nicht deterministische Laufzeit nicht anfällig ist, ist die folgende:
quelle
quelle
Wenn Sie sicherstellen möchten, dass die hinzugefügten Zahlen eindeutig sind, können Sie ein Set-Objekt verwenden
Wenn Sie 2.7 oder höher verwenden, oder importieren Sie das Sets-Modul, wenn nicht.
Wie andere bereits erwähnt haben, bedeutet dies, dass die Zahlen nicht wirklich zufällig sind.
quelle
Ganzzahlen ohne Ersatz zwischen
minval
und abtastenmaxval
:mit jax:
quelle
n_samples
? Was ist Ihre Begründung für diesen Ansatz? Können Sie erklären, was die Vorteile Ihres Ansatzes im Vergleich zu einer der zahlreichen vorhandenen Antworten sind (die meisten davon vor 8 Jahren)?random.shuffle
gewählte Methoden , die Mersenne Twister verwenden, sind viel langsamer als die von numpy (und wahrscheinlich jax) angebotenen Algen. numpy und jax ermöglichen andere Algorithmen zur Erzeugung von Zufallszahlen. jax ermöglicht auch das Kompilieren und Differenzieren von jit, was für die stochastische Differenzierung nützlich sein kann. Auch in Bezug auf ein "möglicherweise großes" Array tun einige der am besten bewerteten Antworten genau dasselberandom.shuffle
, was ich nicht für sündig oder sogar absolut sündig halterandom.shuffle
verwendet Mersenne Twister" verstehen - es ist Fisher-Yates-Shuffle, wie in mehreren Antworten erwähnt. Es hat eine lineare Zeitkomplexität und kann daher möglicherweise nicht asymptotisch langsamer sein als Algorithmen, die von einer anderen Bibliothek angeboten werden, sei es numpy oder auf andere Weise. Wenn numpy schneller ist, liegt dies nur daran, dass es in C implementiert ist. Dies rechtfertigt jedoch nicht die Erzeugung einer großen Permutation (eine, die möglicherweise nicht einmal in den Speicher passt), sondern nur die Auswahl einiger Elemente. Außer Ihrer gibt es keine einzige Antwort, die dies tut.random
Modul ist in Python geschrieben, so dass Sie seine Quelle leicht anzeigen können (versuchenrandom.__file__
).Von der CLI in Win XP:
In Kanada haben wir das 6/49 Lotto. Ich wickle einfach den obigen Code in lotto.bat ein und starte
C:\home\lotto.bat
oder einfachC:\home\lotto
.Weil
random.randint
ich oft eine Zahl wiederhole, benutze ichset
mitrange(7)
und kürze sie dann auf eine Länge von 6.Wenn sich eine Zahl mehr als zweimal wiederholt, beträgt die resultierende Listenlänge gelegentlich weniger als 6.
EDIT: Ist jedoch
random.sample(range(6,49),6)
der richtige Weg.quelle
quelle
print len(result), len(set(result))
. Sie würden erwarten, dassresult
dies nur einmal bei jedem1.0851831788708547256608362340568947172111832359638926... × 10^20
Versuch eindeutige Elemente enthält .