Vous avez une pièce. Vous pouvez le retourner autant de fois que vous le souhaitez.
Vous voulez générer un nombre aléatoire tel que où .
La distribution des nombres doit être uniforme.
C'est facile si :
r = a + binary2dec(flip n times write 0 for heads and 1 for tails)
Et si ?
algorithms
probability-theory
randomness
random-number-generator
Pratik Deoghare
la source
la source
Réponses:
Ce que vous recherchez est basé sur l' échantillonnage de rejet ou la méthode d'acceptation-rejet (notez que la page Wiki est un peu technique).
Cette méthode est utile dans ces types de situations: vous voulez choisir un objet aléatoire dans un ensemble (un entier aléatoire dans l'ensemble dans votre cas), mais vous ne savez pas comment faire cela, mais vous peut choisir un objet aléatoire dans un ensemble plus grand contenant le premier ensemble (dans votre cas, [ a , 2 k + a ] pour certains k tels que 2 k + a ≥ b ; cela correspond à k flips de pièces).[a,b] [a,2k+a] k 2k+a≥b k
Dans un tel scénario, vous continuez à choisir des éléments dans l'ensemble le plus grand jusqu'à ce que vous choisissiez au hasard un élément dans l'ensemble plus petit. Si votre ensemble plus petit est suffisamment grand par rapport à votre ensemble plus grand (dans votre cas, contient au plus deux fois plus d'entiers que [ a , b ] , ce qui est assez bon), cela est efficace.[a,2k+a] [a,b]
Un autre exemple: supposons que vous vouliez choisir un point aléatoire dans un cercle de rayon 1. Maintenant, il n'est pas vraiment facile de trouver une méthode directe pour cela. Nous passons à la méthode d'acceptation-rejet: nous échantillonnons des points dans un carré 1x1 englobant le cercle, et testons si le nombre que nous tirons se trouve à l'intérieur du cercle.
la source
(détails techniques: la réponse correspond à la sélection du nombre )a≤x<b
Puisque vous êtes autorisé à lancer votre pièce autant de fois que vous le souhaitez, vous pouvez obtenir votre probabilité aussi près que vous le souhaitez d'uniformiser en choisissant une fraction (en utilisant le radix binaire: vous retournez le pièce pour chaque chiffre après le point) et multipliez r par b - a pour obtenir un nombre compris entre 0 et [ba-1] (arrondi à un nombre entier). Ajoutez ce numéro à un et vous avez terminé.r∈[0,1] r b−a a
Exemple : disons . 1/3 en binaire est 0,0101010101 .... Ensuite, si votre flip est compris entre 0 et 0,010101 ... votre choix est b . si elle est comprise entre 0,010101 .. et 0,10101010 ... votre choix sera un + 1 , sinon ce sera un + 2 .b−a=3 b a+1 a+2
Si vous retournez votre pièce fois, chaque nombre entre a et b sera choisi avec probabilité 1t a b .1b−a±2−(t+1)
la source
Choisissez un nombre dans la prochaine plus grande puissance de la plage 2 et jetez les réponses supérieures à .b−a
la source
If you want to generaten independent uniform samples of D , then the expected number of coin tosses you need (under the optimal algorithm) is roughly nlog2|D| . More generally, if you want to generate from a distribution of entropy H , you need roughly nH random bits in expectation. An algorithm achieving this is arithmetic decoding, applied to an (ostensibly) infinite sequence of random bits.
la source
If b-a is not a power of 2 then you may have to flip many coins in order to get a result. You may even never get a result, but that is unlikely in the extreme.
Methods
The simplest method is to generate a number in [a, a+2^n), where 2^n >= b-a, until one happens to land in [a, b). You throw away a lot of entropy with this method.
A more expensive method allows you to keep all of the entropy, but becomes very expensive computationally as the number of coin flips / dice rolls increases. Intuitively it is like treating the coin flips as the digits of a binary number to the right of the decimal point, converting that number from base 2 to base a-b after, and returning the digits of that number as they become 'stuck'.
Example
The following code converts rolls of a fair n-sided die into rolls of a fair m-sided die (in your case n=2, m=a-b), with increasing marginal cost as the number of rolls increases. Note the need for a Rational number type with arbitrary precision. One nice property is that converting from n-sided to m-sided and back to n-sided will return the original stream, though perhaps delayed by a couple rolls due to digits having to become stuck.
la source
Generate a binary decimal. Instead of storing it explicitly, just keep track of the min and max possible values. Once those values lie within the same integer, return that integer. Sketch of the code is below.
(Edit) Fuller explanation: Say you want to generate a random integer from 1 to 3 inclusive with 1/3 probability each. We do this by generating a random binary decimal real, x in the range (0, 1). If x < 1/3, return 1, else if x < 2/3 return 2, else return 3. Instead of generating the digits for x explicitly, we just keep track of the minimum and maximum possible values of x. Initially, the min value of x is 0 and the max is 1. If you flip heads first then the first digit of x behind the decimal point (in binary) is 1. The minimum possible value of x (in binary) then becomes 0.100000 = 1/2 and the max is 0.111111111 = 1. Now if your next flip is tails x starts with 0.10. The min possible value is 0.1000000 = 1/2 and the max is 0.1011111 = 3/4. The min possible value of x is 1/2 so you know there's no chance of returning 1 since that requires x < 1/3. You can still return 2 if x ends up being 1/2 < x < 2/3 or 3 if 2/3 < x < 3/4. Now suppose the third flip is tails. Then x must start with 0.100. Min = 0.10000000 = 1/2 and max = 0.100111111 = 5/8. Now since 1/3 < 1/2 < 5/8 < 2/3 we know that x must fall in the interval (1/3, 2/3), so we can stop generating digits of x and just return 2.
The code does essentially this except instead of generating x between 0 and 1 it generates x between a and b, but the principle is the same.
Remarque: J'ai testé ce code par rapport à la méthode d'acceptation / rejet et les deux produisent des distributions uniformes. Ce code nécessite moins de lancers de pièces que d'accepter le rejet, sauf lorsque b - a est proche de la puissance suivante de 2. Ex si vous voulez générer a = 0, b = 62, alors accepter / rejeter fait mieux. J'ai pu prouver que ce code ne peut utiliser en moyenne pas plus de 2 tours de pièces de plus qu'accepter / rejeter. D'après ma lecture, il semble que Knuth et Yao (1976) aient donné une méthode pour résoudre ce problème et prouvé que leur méthode est optimale dans le nombre attendu de lancers de pièces. Ils ont en outre prouvé que le nombre attendu de flips doit être supérieur à l'entropie de Shannon de la distribution. Je n'ai pas pu trouver une copie du texte du papier cependant et serais curieux de voir quelle est leur méthode. (Mise à jour: vient de trouver une exposition de Knuth Yao 1976 ici:http://www.nrbook.com/devroye/Devroye_files/chapter_fifteen_1.pdf but I have not yet read it). Someone also mentioned Han Hoshi in this thread which seems to be more general and solves it using a biased coin. See also http://paper.ijcsns.org/07_book/200909/20090930.pdf by Pae (2009) for a good discussion of the literature.
la source
The simple answer?
Ifb−a is not a power of 2, then after generating r , check whether it is in-range, and if not, generate it again.
The most likely time you will have to re-generater is when b−a=2n+1 for some integer n , but even then it will have a greater than 50% chance of falling within range on each generation.
la source
This is a proposed solution for the case when b - a does not equal 2^k. It is supposed to work in fixed number of steps (no need to throw away candidates which are outside your expected range).
However, I am not sure this correct. Please critique and help describe the exact non-uniformity in this random number generator (if any), and how to measure/quantify it.
Firstly convert to equivalent problem of generating uniformly distributed random numbers in range [0, z-1] where z = b - a.
Also, let m = 2^k be the smallest power of 2 >= z.
As per the solution above, we already have a uniformly distributed random number generator R(m) in range [0,m-1] (can be done by tossing k coins, one for each bit).
The while loop runs at most 3 times, giving next random number in fixed number of steps (best case = worst case).
See a test program for numbers [0,2] here: http://pastebin.com/zuDD2V6H
la source
Theoretically optimal algorithm
Here is an improvement of the other answer I posted. The other answer has the advantage that it is easier to extend to the more general case of generating one discrete distribution from another. In fact, the other answer is a special case of the algorithm due to Han and Hoshi.
The algorithm I will describe here is based on Knuth and Yao (1976). In their paper, they also proved that this algorithm achieves the minimum possible expected number of coin flips.
To illustrate it, consider the Rejection sampling method described by other answers. As an example, suppose you want to generate one of 5 numbers uniformly [0, 4]. The next power of 2 is 8 so you flip the coin 3 times and generate a random number up to 8. If the number is 0 to 4 then you return it. Otherwise, you throw it out and generate another number up to 8 and try again until you succeed. But when you throw out the number, you just wasted some entropy. You can instead condition on the number you threw out to reduce the number of future coin flips you'll need in expectation. Concretely, once you generate the number [0, 7], if it is [0, 4], return. Otherwise, it's 5, 6, or 7, and you do something different in each case. If it's 5, flip the coin again and return either 0 or 1 based on the flip. If it's 6, flip the coin and return either 2 or 3. If it's 7, flip the coin; if it's heads, return 4, if it's tails start over.
The leftover entropy from our initial failed attempt gave us 3 cases (5, 6, or 7). If we just throw this out, we throw away log2(3) coin flips. We instead keep it, and combine it with the outcome of another flip to generate 6 possible cases (5H, 5T, 6H, 6T, 7H, 7T) which let's us immediately try again to generate a final answer with probability of success 5/6.
Here is the code:
la source