最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Using Random() with a Bias - Stack Overflow

programmeradmin0浏览0评论

Suppose I have an array

var list = ['a', 'b', 'c', 'd'];

and I want to select one value from List at random. If it is pletely random, each will have a 25% chance. Is there a way to select a value at random with a bias like so:

var bias = [0.1, 0.2, 0.1, 0.6];

(bias of course adds up to 1)

So 'a' has a 10% chance of being selected and 'b' has a 20% chance of being selected, etc

Edit: I know I can just modify do var list = ['a', 'b', 'b', 'c', 'd', 'd', 'd', 'd', 'd', 'd'] and just select a value at random but I am looking for a more efficient way of doing this by just having an array that contains the bias.

Suppose I have an array

var list = ['a', 'b', 'c', 'd'];

and I want to select one value from List at random. If it is pletely random, each will have a 25% chance. Is there a way to select a value at random with a bias like so:

var bias = [0.1, 0.2, 0.1, 0.6];

(bias of course adds up to 1)

So 'a' has a 10% chance of being selected and 'b' has a 20% chance of being selected, etc

Edit: I know I can just modify do var list = ['a', 'b', 'b', 'c', 'd', 'd', 'd', 'd', 'd', 'd'] and just select a value at random but I am looking for a more efficient way of doing this by just having an array that contains the bias.

Share Improve this question asked Jan 5, 2015 at 23:37 BijanBijan 8,72221 gold badges102 silver badges162 bronze badges 2
  • 1 Unless your list gets really large, (which depends on the exact requirements, such as if you want something to be picked 2.3486% of the time) I suspect that your quick and dirty way is "more efficient" than the answers below which require summing things and their own array of floats. – user949300 Commented Jan 5, 2015 at 23:47
  • @user949300: The cumulative bias array is nice if you need to pull several samples from the same list with same probabilities, so you can (and should) precalculate it. It is not required: you can just go summing-and-sequentially-searching every time you need a sample if the biases change all the time, or just want to do it once (however, then you can't use binary search). It is also the only way to do it if biases are not all integral multiples. – Amadan Commented Jan 6, 2015 at 0:47
Add a ment  | 

3 Answers 3

Reset to default 6

Make a cumulative bias list:

var sum = 0;
var cumulativeBias = bias.map(function(x) { sum += x; return sum; });

Then make a random number from 0 to the sum (i.e. cumulativeBias[cumulativeBias.length - 1]):

var choice = Math.random() * sum;

Then search for the first element in cumulativeBias that is bigger than choice. You can use binary search for speed, but for short lists a sequential search is good enough. The index of that element is the chosen index. For example, something like:

var chosenIndex = null;
cumulativeBias.some(function(el, i) {
    return el > choice ? ((chosenIndex = i), true) : false;
});
chosenElement = list[chosenIndex];

I have written this in the past in the following way:

Replace your bias with a running total - i.e. add bias[0] to bias[1], then add bias[1] to bias[2], then add bias[2] to bias[3].

In your above example, you would get var bias = [0.1, 0.3, 0.4, 1.0] - the last one should always be 1, otherwise you have done something wrong.

Now pick a random number between 0 and 1.0; find the largest number in the bias array, that is smaller than your random number. Pick the corresponding value from your list array.

Edit: @Amadan is right. I meant, find the smallest number in the bias array, that is larger than your random number. My "smallest" and "largest" were the wrong way round :)

Since your bias is simple, you can just make an array that offers 10% 'a', 20% 'b' and so on like this and then just pick a random value from that:

var choices = ['a', 'b', 'b', 'c', 'd', 'd', 'd', 'd', 'd', 'd'];
var biasVal = choices[Math.floor(Math.random() * choices.length)];

The choices array could be built programmatically if needed. It would only have to be built once and from then on the selection of random choices would be significantly faster with this method.

发布评论

评论列表(0)

  1. 暂无评论