srand() und rand() auslagern
-
@Unterfliege ad 2: Das, was ich andernorts auch schon gesagt habe. Den mt mit nur 32 bits seeden ist. ... doof.
-
@Swordfish Aber das dürfte eigentlich nicht die Periodenlänge des Algorithmuses ändern, oder irre ich mich da? Und ich weiß ja noch nicht einmal, ob @TGGC das meinte.
Deinen Artikel habe ich deswegen aber ja auch schon verlinkt.
-
@Unterfliege Die Periodenlänge nicht, aber die Anzahl der möglichen Perioden. Ja, meint er.
-
@TGGC sagte in srand() und rand() auslagern:
Speicher und Laufzeit ist um ein Vielfaches erhöht.
Speicher ja. Laufzeit von
mt19937
ist aber überraschenderweise wirklich sehr gut. Davon abgesehen hab ich an deiner Kritik nichts zu kritisieren xD
-
@Swordfish also unter einer Periode verstehe ich die Anzahl an Zufällen, die der Algorithmus generieren kann, bevor er sich wiederholt. Dabei ist es dann wohl eher so, dass die Aufrufe nach 2^32 Aufrufen schlechten/gar keinen Zufall liefern (ich habe mich mit dem MT ehrlich gesagt nie direkt auseinandergesetzt). Ich will allerdings auch nicht ausschließen, dass ich diesbezüglich falsch liege.
@hustbaer was nutzt du denn dann eigentlich als Alternative? Separate lib oder seedest du einfach nur den
mt19937
besser (wie auch in dem Artikel, den ich oben verlinkt habe, gezeigt wird)? Oder akzeptierst du einfach die Nachteile?
-
@Unterfliege sagte in srand() und rand() auslagern:
also unter einer Periode verstehe ich die Anzahl an Zufällen, die der Algorithmus generieren kann, bevor er sich wiederholt.
Ja.
@Unterfliege sagte in srand() und rand() auslagern:
Dabei ist es dann wohl eher so, dass die Aufrufe nach 2^32 Aufrufen schlechten/gar keinen Zufall liefern
Wenn du mit 32 bit seedest hast du danach wieder die selben Sequenzen.
-
@Swordfish sagte in srand() und rand() auslagern:
Wenn du mit 32 bit seedest hast du danach wieder die selben Sequenzen.
Okay, dann habe ich das missverstanden. Ich ging davon aus, dass
std::mt19937
die restlichen Bits von seinem state einfach mit 0 intialisiert/uninitialisiert nutzt.
-
@Swordfish sagte in srand() und rand() auslagern:
Dabei ist es dann wohl eher so, dass die Aufrufe nach 2^32 Aufrufen schlechten/gar keinen Zufall liefern
Wenn du mit 32 bit seedest hast du danach wieder die selben Sequenzen.
Auch wenn man nur mit 32 bit seeded, ist die Periode dennoch deutlich länger. Du hast eben nur 2^32 initial states. Die Periodenlänge ist, Achtung, man könnte es am Namen erraten, (Quelle). Diese ultralange Periode ist neben der guten Verteilung der Zahlen ja gerade toll an MT.
-
@wob Du hast mich falsch verstanden. Wenn man mit einem wert 0 <= 2^32-1 seeded hat man eine Sequenz der länge $Periodenlänge für 0, eine Sequenz der länge $Periodenlänge für 1, eine Sequenz der länge $Periodenlänge für 2, ...
-
@Unterfliege sagte in srand() und rand() auslagern:
@hustbaer was nutzt du denn dann eigentlich als Alternative? Separate lib oder seedest du einfach nur den mt19937 besser (wie auch in dem Artikel, den ich oben verlinkt habe, gezeigt wird)? Oder akzeptierst du einfach die Nachteile?
Das letzte mal wo ich gute Zufallszahlen* brauchte hab ich
mt19937
genommen und überCryptGenRandom
geseedet. Auf POSIX Systemen kann man/dev/random
oder/dev/urandom
verwenden. Heutzutage würde ich aber eherstd::random_device
verwenden.*: Der
mt19937
ist lange nicht so gut wie viele meinen. Wenn du nen guten, schnellen, einfachen Generator willst, schau dir die Xoroshiro Familie an. Bzw. google einfach selbst mal nach dem Thema.
-
@hustbaer sagte in srand() und rand() auslagern:
Der mt19937 ist lange nicht so gut wie viele meinen.
Naja, ich würde mal sagen, dass der
am besten General-Purpose-Zwecke erfüllendebeste Pseudo Random Number Generator ist, den es fertig im C++-Standard gibt. Daher empfehle ich diesen im Regelfall für alles mögliche. Wenn man mehr braucht: gerne, spricht nichts dagegen!Heutzutage würde ich aber eher std::random_device verwenden.
Ja? Als ich das hier mal vorgeschlagen hatte für ein paar Zufallszahlen, warst du vor noch nicht mal einem Jahr noch anderer Meinung:
https://www.c-plusplus.net/forum/topic/347207/array-wörter-zufällig-aufrufen/12
-
@wob
random_device()
zum seeden, nicht als RNG.
-
Genau!
@wob Alles nach "hab ich mt19937 genommen" bezieht sich auf's Seeden. CryptGenRandom, /dev/random, /dev/urandom und std::random_device, alles gut zum Seeden geeignet, nix davon gut zum Erzeugen guter Zufallssequenzen geeignet. Zumindest nicht ohne "Nachbearbeitung" der Daten, und nicht wenn man gute Performance will.
-
Ok? Ist es dann immernoch aus kryptografischer Sicht legitim, z.B. CryptGenRandom nur als Seed für den Mt19937 zu nutzen? Beispiel wäre die Erstellung eines Salts für Hashverfahren. Oder entstehen da dann wieder Lücken, welche sich Dritte zu Nutze machen können?
-
@hustbaer sagte in srand() und rand() auslagern:
@wob Alles nach "hab ich mt19937 genommen" bezieht sich auf's Seeden. CryptGenRandom, /dev/random, /dev/urandom und std::random_device, alles gut zum Seeden geeignet, nix davon gut zum Erzeugen guter Zufallssequenzen geeignet. Zumindest nicht ohne "Nachbearbeitung" der Daten, und nicht wenn man gute Performance will.
ich dachte, urandom wäre der standard? mein testprogramm (1,2 GHz) hat jedenfalls knapp 3,3s für 1 Gb gebraucht. wie schnell muss das denn sein?
@Zhavok sagte in srand() und rand() auslagern:
Ok? Ist es dann immernoch aus kryptografischer Sicht legitim, z.B. CryptGenRandom nur als Seed für den Mt19937 zu nutzen?
laut wikipedia ist das teil nicht für kryptografische anwendungen geeignet.
-
@Zhavok
mt19937 ist für Crypto Zeugs nicht zu gebrauchen.
-
@Wade1234 sagte in srand() und rand() auslagern:
ich dachte, urandom wäre der standard?
Standard für was?
mein testprogramm (1,2 GHz) hat jedenfalls knapp 3,3s für 1 Gb gebraucht. wie schnell muss das denn sein?
Normalerweise will man nicht Megabyteweise Zufallszahlen am Stück generieren sondern an verschiedenen Stellen pro Durchlauf ein oder zwei Zufallszahlen ziehen.
-
@hustbaer sagte in srand() und rand() auslagern:
Standard für was?
für die erzeugung von zufallszahlen aller art auf unix-systemen. edit: also vorausgesetzt, man möchte diese zufallszahl über das betriebsystem beziehen.
Normalerweise will man nicht Megabyteweise Zufallszahlen am Stück generieren sondern an verschiedenen Stellen pro Durchlauf ein oder zwei Zufallszahlen ziehen.
macht das denn so einen unterschied?
-
@Wade1234 sagte in srand() und rand() auslagern:
macht das denn so einen unterschied?
Was meinst du geht schneller, 1-2 Multiplikationen und 2-3 ADDs/XORs, oder
read()
für 8 Byte aufrufen?
-
naja wenn read schneller wäre, würdest du mich das wahrscheinlich nicht fragen. evtl. - sag ich mal - 256 kB in einen puffer laden und bei bedarf auslesen?