开发者

Elegant way to bias random boolean

I'd like to create a random boolean in JavaScript, but I want to take the previous value into account. If the previous value was true, I want it to be more likely for the next value to be true. At the moment I've got this (this is in the context of a closure - goUp and lastGoUp are locals to the containing scope):

function setGoUp() {
    goUp = getRandomBoolean();

    if(lastGoUp) {
        goUp = getRandomBoolean() || goUp;
    }
    else {
        goUp = getRandomBoolean() && goUp;
    }
    lastGoUp = goUp;
}

So, the algorithm goes:

  1. Get a random boolean
  2. If the random boolean from the previous call was True:

    a) get another random boolean, and or these two together

    b) else get another random boolean and and these together.

I'm sure this algorithm could be simplified. I wondered about doing:

if(lastGoUp && goUp) {
    goUp = goUp * (getRandomBool开发者_如何学JAVAean() || goUp);
}

but that seems really dirty.

There's also a problem with this algorithm which means that I can only double the chance of getting the same boolean again - I can't tweak it easily. Any ideas?


You should define the distribution you want, but maybe you are looking for the following?

if (lastGoUp) {
    goUp = Math.random() < 0.8;
} else {
    goUp = Math.random() < 0.2;
}


Instead of getting a random boolean, get a random number, say between 0 and 99. Keep a threshold value instead of the last number, and adjust the threshold according to the result:

var threshold = 50;

function setGoUp() {
   goUp = getRandomNumber() < threshold;
   threshold += goUp ? -10 : 10;
}

This would keep a running tab, so if you get consecutive results that are the same, the probability would keep falling for that result.

If you only want to consider the last result, you would instead set the threshold to a specific value:

threshold = goUp ? 40 : 60;


If you only want the probability of the next event to depend on the current value, and not the history of values up til now, what you want is called a Markov process. Often these are implemented with a 2D table of probabilities that you look up (prob of each next outcome given current one), but for a simple bool-valued event, an if statement is sufficient (see meriton's answer; note that it corresponds to a table of probabilities [0.8 0.2; 0.2 0.8]).

If you want something that gets more likely, say, the more successes you get in a row, then you need to devise a sequence of probabilities for success that perhaps approaches, but does not exceed, 1. There are any number of formulas which can do this, depending on how strong you want the bias to become and how quickly you want it to get there.


I would just make the probability of getting value true be an explicit float variable p. Then I could tweak it easily, by increasing p in some way if I got true last time or by doing nothing with it if I got 'false'.


Can replace Math.random for a better randomizer.

var setGoUp = (function(){
   var last;
   return function(){
       // if last 66% chance for true else 50% chance of true.
       return !!(last ? Math.random()*3 : Math.random()*2);
   }
}());

!! converts anything to a boolean, 0 = false.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜