How to choose randomly in a certain ratio
I want to choose randomly* between two alternatives with unequal probability.
For instance, when the user presses a button, 25% of the time it wou开发者_如何学JAVAld make sound A and 75% of the time, sound B. I can manually do easy ratios like 1:4 and 2:4 but I'm having trouble with ratios like 3:5.
What is the generic way to think about this?
*I mean unpredictable when looked at one-by-one. I notice any question with the word random in it gets a Mensa of pedants.
The ration 3:5 is equivalent to 37.5% of the time or 0.375 (3 times it's A, 5 times it's B, so 3/8 is 37.5%). So you can calculate it like this:
random() < 0.375 ? "A" : "B"
From
http://en.wikipedia.org/wiki/Ratio
If there are 2 oranges and 3 apples, the ratio of oranges to apples is shown as 2:3, whereas the fraction of oranges to total fruit is 2/5.
For 3:5 you can add them together to get 8, and pick a random integer less than 8. If it's 0, 1, or 2 (three chances) you choose A, and if it's 3, 4, 5, 6, or 7 (five chances) you choose B. Code-wise you'd just check whether your random number is less than 3.
For something like 3:5:4, you'd pick a random number less than 12 (3+5+4) and if it's less than 3 you choose A, otherwise if it's less than 8 (3+5) you choose B, otherwise you choose C.
This can generalize to any number of alternatives, but it's inefficient with lots of alternatives since you have to check the random number against each threshold, which is O(n). This SO question seems to provide some more efficient (but more complex) algorithms for weighted random selection with larger numbers of alternatives.
If you have access to a uniform random number distribution between 0 and 1 you can do the following:
Convert the ratio into a fraction, so the ratio will then become some number x. (For example 3:2 will become 3/5 or 0.6) Take a random number y from the uniform [0,1] distribution. If y < x choose the first alternative, otherwise choose the second alternative.
Assuming your random number generator gives back a double value between 0.0 and 1.0, you just do a comparison to the exact ratio you want. In the case of 3 out of 5, you'd check to see if the random value was less than 0.6.
if(rand < 0.6) {
playSound(A);
}
else {
playSound(B);
}
if (random() % (A+B) < A)
do_A()
else
do_B();
精彩评论