开发者

probability in javascript help?

开发者 https://www.devze.com 2023-01-21 11:21 出处:网络
Sorry, I\'开发者_Python百科m new to JS and can\'t seem to figure this out: how would I do probability?

Sorry, I'开发者_Python百科m new to JS and can't seem to figure this out: how would I do probability?

I have absolutely no idea, but I'd like to do something: out of 100% chance, maybe 0.7% chance to execute function e(); and 30% chance to execute function d(); and so on - they will add up to 100% exactly with a different function for each, but I haven't figured out exactly how to do this in any form.

What I found is mostly strange high school math tutorials "powered by" Javascriptkit or something.


For instance we define a number of functions

function a () { return 0; }
function b () { return 1; }
function c () { return 2; }

var probas = [ 20, 70, 10 ]; // 20%, 70% and 10%
var funcs = [ a, b, c ]; // the functions array

That generic function works for any number of functions, it executes it and return the result:

function randexec()
{
  var ar = [];
  var i,sum = 0;


  // that following initialization loop could be done only once above that
  // randexec() function, we let it here for clarity

  for (i=0 ; i<probas.length-1 ; i++) // notice the '-1'
  {
    sum += (probas[i] / 100.0);
    ar[i] = sum;
  }


  // Then we get a random number and finds where it sits inside the probabilities 
  // defined earlier

  var r = Math.random(); // returns [0,1]

  for (i=0 ; i<ar.length && r>=ar[i] ; i++) ;

  // Finally execute the function and return its result

  return (funcs[i])();
}

For instance, let's try with our 3 functions, 100000 tries:

var count = [ 0, 0, 0 ];

for (var i=0 ; i<100000 ; i++)
{
  count[randexec()]++;
}

var s = '';
var f = [ "a", "b", "c" ];

for (var i=0 ; i<3 ; i++)
  s += (s ? ', ':'') + f[i] + ' = ' + count[i];

alert(s);

The result on my Firefox

a = 20039, b = 70055, c = 9906

So a run about 20%, b ~ 70% and c ~ 10%.


Edit following comments.

If your browser has a cough with return (funcs[i])();, just replace the funcs array

var funcs = [ a, b, c ]; // the old functions array

with this new one (strings)

var funcs = [ "a", "b", "c" ]; // the new functions array

then replace the final line of the function randexec()

return (funcs[i])(); // old

with that new one

return eval(funcs[i]+'()');


Something like this should help:

var threshhold1 = 30.5;
var threshhold2 = 70.5;
var randomNumber = random() * 100;
if (randomNumber < threshhold1) {
   func1()
}
else if (randomNumber < threshhold2) {
   func2()
}
else {
   func3()
}

This will execute func1() with 30.5% probability, func2() with 40%, and func3() with 29.5%.

You could probably do it more elegantly using a dictionary of threshholds to function pointers, and a loop that finds the first dictionary entry with a threshhold greater than randomNumber.


// generate cumulative distribution function from weights
function cdf(weights) {
    // calculate total
    var total = 0;
    for(var i=0; i<weights.length; i++) {
        total += weights[i];
    }
    // generate CDF, normalizing with total
    var cumul = [];
    cumul[0] = weights[0]/total;
    for(var i=1; i<weights.length; i++) {
        cumul[i] = cumul[i-1] + (weights[i]/total);
    }
    return cumul;
}

// pick the index using the random value
function selectInd(cumul,rand) {
    for(var i=0; (i < cumul.length) && (rand > cumul[i]); ++i) {};
    return i;
}

Code block to use the above

// setup (do this once)
var weights = [70,20,10];
var cumul = cdf(weights)

// get the index and pick the function
var ran = Math.random(); // 0 : 1
var func = funcs[selectInd(cumul,ran)]; 

// call the function
var someArgVal = 5;
var myResult = func(someArgVal);

// do it in one line
var myResult = (funcs[selectInd(cumul,Math.random())])(someArgVal);

Simplify calling code with a reusable object

function CumulDistributor(cumul,funcs) {
    var funcArr = funcs;
    var cumulArr = cumul;
    function execRandomFunc(someArg) {
        var func = funcArr[selectInd(cumulArr,Math.random())];
        return func(someArg);
    }
}

// example usage
var cdistor = new CumulDistributor(cumul,funcs);
var myResult = cdistor.execRandomFunc(someArgValue);


var decide = function(){ 
    var num = parseInt(Math.random() * 10) + 1; // assigns num randomly (1-10)
    num > 7 ? d() : e(); // if num > 7 call d(), else call e() 
};


Look up how to get random numbers in JavaScript, and then depending on where that number falls, call each function.


Sounds like what you really want is the Javascript random() function.

0

精彩评论

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

关注公众号