2017-10-23 7 views
2

Sie eine int randBit() Funktion gegeben sind Angenommen, die zurückkommt, gleichmäßig verteilt, 0 oder 1.eine zufällige int gegeben eine zufällige Bit-Funktion erzeugen

schreiben randNumber (int max) Funktion.

Dies ist meine Implementierung, aber ich kann nicht beweisen/widerlegen, dass es richtig ist.

// max number of bits 
    int i = (int)Math.floor(Math.log(max)/Math.log(2)) + 1; 

    int ret = randBit(); 
    while (i-- > 0) { 
     ret = ret << 1 | randBit(); 
    } 

    return ret; 

Die grundlegende Idee, die ich hatte, ist, dass

  • vorhanden, um die Anzahl der Bits finden in der Anzahl
  • dann erzeugen die Anzahl von kontinuierlich die verketten LSB bis der Bitlänge ist
  • erfüllt
+0

Der Ansatz ist sinnvoll für Potenzen von 2 (oder Potenz von 2 minus eins: Sie machen nicht klar, wenn "max" ist inklusive oder exklusiv), aber was passiert, wenn die Zahl keine Potenz von 2 ist Zum Beispiel, wenn 'max' 6 ist. – BeeOnRope

+0

Wenn max 2 ist, bekomme ich Ergebnisse zwischen 0 und 7. – yacc

Antwort

1

Der Ansatz, einen int mit zufälligen Bits zu füllen, ist meines Erachtens der richtige Weg. Da jedoch nur Ihr Algorithmus funktioniert, wenn maximale Leistung von 2 ist und ausgeschaltet ist durch eine in der Schleife, würde ich diese Änderung vorschlagen:

// max number of bits 
int i = (int)Math.floor(Math.log(max)/Math.log(2)) + 1; 

int rnd = 0; 
int mask = 1; 

while (i-- > 0) { 
    rnd = rnd << 1 | randBit(); 
    mask <<= 1; // or: mask *= 2 
} 
double q = (double)rnd/mask; // range is [0, 1) 
return (int)((max + 1) * q); 

Werfen wir einen Blick auf diese:

i wird immer gleich der Anzahl der Bits sein, die max belegt. Wenn die Schleife beendet ist, enthält rnd diese Anzahl von Bits, die zufällig mit 0 oder 1 gefüllt sind, und mask-1 enthält diese Anzahl von Bits, die mit 1s gefüllt sind. Man kann also davon ausgehen, dass der Quotient von rnd und mask-1 gleichmäßig zwischen 0 und 1 verteilt ist. Dies multipliziert mit max würde Ergebnisse im Bereich zwischen 0 und max, ebenfalls gleichverteilt, in Bezug auf Floating/Real-Werte ergeben.

Jetzt muss dieses Ergebnis auf ganze Zahlen abgebildet werden, und natürlich möchten Sie auch, dass sie gleichmäßig verteilt sind. Der einzige Haken hier ist die 1. Wenn der Quotient von rnd und mask-1 genau 1 ist, würde es einen Kantenfall geben, der Probleme bei der Skalierung auf den gewünschten Ergebnisbereich verursachen würde: Es wären 0 .. max-1 Werte gleichmäßig verteilt, aber max wäre eine seltene Ausnahme.

Um auf diese Bedingung zu achten, muss der Quotient so aufgebaut sein, dass er von 0 bis 1 reicht, aber mit 1 exclusiv. Dies wird erreicht durch rnd/mask. Dieser Bereich kann leicht auf gleichmäßig gespreizte Ganzzahlen 0 .. max abgebildet werden, indem mit max+1 multipliziert und an int.

+0

sollte nicht' (double) rnd/mask' yeild [0,1] (1 inclusive)? Weil es möglich ist, dass rnd alles 1s ist –

+0

Bitte erklären Sie, wie die letzte (int) Umwandlung wird eine gleichmäßige Verteilung zu erzeugen (zum Beispiel in [0,5) gegeben 8 gleichwahrscheinliche Kombinationen von 3 Bits 000 bis 111) –

+0

@aka .nice Bei 'max == 4' (3 Bits) liegt' (double) rnd/mask' im Bereich von 0 bis 7/8. Dies multipliziert mit 5 (max + 1) ergibt "[0/8, 35/8]". So symbolisiert 'rnd' folgendes: 000..001 => 0, 010..011 => 1, 100 => 2, 101..110 => 3, 111 => 4. – yacc

Verwandte Themen