2009-03-15 5 views
14

MitObjective C: Modulo Bias

value = arc4random() % x 

Wie kann ich vermeiden oder Modulo-Bias beseitigen?

Vielen Dank.

BTW, zumindest nach Wikipedia, Modulo Bias ist ein Problem bei der Programmierung Glücksspiele.

+1

Betrachten Wieder Markierung Zoidberg Antwort als richtig, da es die kanonische richtige Antwort ist nach die Autoren von arc4random(). – MikeyWard

+2

[Was ist Modulo Bias] (http://stackoverflow.com/questions/10984974/why-do-people-say-there-is-modulo-bias-when-using-a-random-number-generator)? – bobobobo

Antwort

14

arc4random gibt eine 32-Bit-Ganzzahl ohne Vorzeichen zurück (0 bis 2 -1).

Es wird wahrscheinlich keine noticable Modulo Bias für klein genug x sein. Allerdings, wenn Sie wirklich wollen, um sicher zu sein, dies zu tun:

y = 2 p wo 2 p-1 < x ≤ 2 p

val = arc4random() % y; 
while(val >= x) 
    val = arc4random() % y; 
+0

Gern geschehen. =) –

+0

Wenn ich mich erinnere, gibt es so etwas in Pythons Zufallszahlengenerator. –

+3

Ich stolperte zufällig über dieselbe Aufgabe, C-Implementierung kann in OpenBSD 'arc4random_uniform()' unter [src/sys/dev/rnd.c] gefunden werden (http://www.openbsd.org/cgi-bin/cvsweb/ src/sys/dev/rnd.c? rev = 1.140; content-type = Text% 2Fplain) – SashaN

2

Wenn der Maximalwert von arc4randomx mod größer als x, ignoriert alle Werte größer als die größten arc4random-max mod x, rief arc4random wieder statt.

4
u_int32_t maxValue = ~((u_int32_t) 0);  // equal to 0xffff... 
maxValue -= maxValue % x;     // make maxValue a multiple of x 
while((value = arc4random()) >= maxValue) { // loop until we get 0 ≤ value < maxValue 
} 
value %= x; 

obwohl es sei denn, Sie x unter einer Million verwenden (oder mehr) würde ich nicht darum kümmern

1
u_int32_t maxValue = ~((u_int32_t) 0);  // equal to 0xffff... 
maxValue -= maxValue % x;     // make maxValue a multiple of x 
while((value = arc4random()) >= maxValue) { // loop until we get 0 ≤ value < maxValue 
} 
value %= x; 

Etwas pedantisch Einwand gegen cobbal Antwort. Es "funktioniert", dh es entfernt die Modulo-Verzerrung, aber es weist mehr Werte als nötig zurück. Der extremste Fall ist x = 2^31. Alle Werte von arc4random() sollten hier akzeptiert werden, aber der Code wie geschrieben wird die Hälfte von ihnen zurückweisen.

Stattdessen fügen 1 auf die Initialisierung von maxValue (das bringt es auf 2^32, so finden Sie eine 64-Bit-int verwenden müssen), und es ist dann richtig. Sie können auch vermeiden, einen 64-Bit-Int zu verwenden. Testen Sie vorher, ob 2^32% x == 0, wenn also alle arc4random() Werte akzeptabel sind und Sie die Schleife überspringen können, andernfalls können Sie maxValue bei 32 Bits beibehalten, indem Sie 2^32% x bei der Initialisierung subtrahieren.

47

Verwendung arc4random_uniform(x). Das macht es für dich.

Nach der Manpage:

arc4random_uniform() wird eine gleichmäßig verteilte Zufallszahl kleiner als upper_bound zurück. arc4random_uniform() wird über Konstruktionen wie arc4random() % upper_bound empfohlen, da es "modulo bias" vermeidet, wenn die obere Grenze keine Zweierpotenz ist.

+5

Diese Antwort ist besser als die angenommene. –

-1

die Methode unten. Es vermeidet "modulo bias" und es ist schnell auf iphone. Speichern Sie einige CPU-Zyklen.

WENN Sie wollen 4-7:

(random()/(float)RAND_MAX)*3+4 

oder wenn Sie wollen 0-8

(random()/(float)RAND_MAX)+8 
+0

'random()' ist kein sicherer Zufallsgenerator, benutze es nicht! – dchest