views:

70

answers:

4

Sorry, I'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.

+2  A: 

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

Robert Massaioli
+2  A: 

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

philfreo
I looked at random function, but I couldn't really figure out how exactly to do it because it just returns random numbers and I have no clue how to compare 0.4% of a random number or something..
jen
Find a way to get a random integer between 1 and 10, inclusive. Then check to see if the number is 1, 2, or 3 in order to check for 30% of the cases.
philfreo
I'm not sure how that would fit with the rest though - there are about 25 functions that are under 0.5%. Should I ceil or floor for 1 and 10 or does it not matter asl ong as it's consistent?
jen
You can modify the upper/lower range of the random number to be whatever you want. It can even return decimal numbers. The point is to use random() however you'd like to get the % chance you want to act on
philfreo
+1  A: 

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.

Andrew Cooper
I've been trying something like this but I can't seem to get it work for a very large amount of identical amounts (a lot of 0.50%)
jen
jen
Just set the threshholds to 0.5, 1.0, 1.5, 2.0, ... . You only need to check each threshhold once because once one threshhold matches the other greater threshholds won't be checked.
Andrew Cooper
A: 

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]+'()');
ring0
For some reason, it just says `Error: funcs[i] is not a function` (for the line `return (funcs[i])();`) after adding my own arrs. The count, probas and funcs arrays are all fine, and all the functions exist. Not sure if having numbers in the fucntion names and a LOT of duplicate probabilities would matter.
jen
Are you sure you didn't create a function name that is not in the funcs array, or, for instance, that a func name like `i` interferes with the other variables? Please try with my example. If it works, it should work with any function, as long as their name is correct, is in the funcs array and does not hide another existing variable (or, reversely, would be hidden by another variable).
ring0
Please check my **edit** it should work with any browser. (the above comment about variables hiding is still true however :-)
ring0