2010-10-21 51 views
7

Lo siento, soy nuevo en JS y parece que no puedo resolver esto: ¿cómo podría hacerlo?probabilidad en javascript ayuda?

No tengo ni idea, pero me gustaría hacer algo: 100% de posibilidades, quizás 0.7% de posibilidad de ejecutar la función e(); y 30% de ejecutar la función d(); y así sucesivamente - se sumarán a 100% exactamente con una función diferente para cada uno, pero no he descubierto exactamente cómo hacerlo de ninguna forma.

Lo que encontré es en su mayoría extraños tutoriales de matemáticas de la escuela secundaria "powered by" Javascriptkit o algo así.

+0

estas probabilidades son establecidos? como en, ¿vas a tener una tabla de probabilidades que se vinculen a funciones? o son dinámicos, basados ​​en la entrada? –

+0

Se establece la probabilidad, con la tabla que vincula a la función. – jen

Respuesta

15

Por ejemplo definimos una serie de funciones

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 

Esa función genérica funciona para cualquier número de funciones, lo ejecuta y devuelve el resultado:

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])(); 
} 

Por ejemplo, vamos a tratar con nuestras 3 funciones, 100000 intentos:

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); 

El resultado en mi Firefox

a = 20039, b = 70055, c = 9906 

Así una carrera alrededor del 20%, b ~ 70% y c ~ 10%.


Editar siguiente comentarios.

Si su navegador tiene una tos con return (funcs[i])();, basta con sustituir la matriz funcs

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

con esta nueva (cuerdas)

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

vuelva a colocar la línea final de la función randexec()

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

con esa nueva

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

Por alguna razón, solo dice 'Error: funcs [i] no es una función' (para la línea' return (funcs [i])(); ') después de agregar mis propios arrs. Los arreglos de conteo, probas y funcs están bien, y todas las funciones existen. No estoy seguro de si tener números en los nombres de las máquinas y MUCHAS probabilidades duplicadas sería importante. – jen

+0

¿Estás seguro de que no creaste un nombre de función que no está en la matriz de funcs, o, por ejemplo, que un nombre de función como 'i' interfiere con las otras variables? Por favor prueba con mi ejemplo. Si funciona, debería funcionar con cualquier función, siempre que su nombre sea correcto, está en la matriz de funcs y no oculta otra variable existente (o, a la inversa, estaría oculta por otra variable). –

+0

Compruebe mi ** edición ** debería funcionar con cualquier navegador. (El comentario anterior sobre la ocultación de variables sigue siendo cierto, sin embargo :-) –

1

Suena como lo que realmente quieres es el Javascript random() function.

+0

POR FAVOR, POR FAVOR, nunca remita a las personas a la 'documentación de W3school', use en su lugar la documentación oficial de javascript en Mozilla https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random tal vez en 2010 esto no existía? – ncubica

1

Busque cómo obtener números aleatorios en JavaScript y luego, dependiendo de dónde caiga ese número, llame a cada función.

+0

Miré la función aleatoria, pero no pude averiguar cómo hacerlo exactamente porque solo devuelve números aleatorios y no tengo ni idea de cómo comparar el 0,4% de un número aleatorio o algo .. – jen

+1

Encuentra una manera de obtenerlo un entero aleatorio entre 1 y 10, inclusive. Luego verifique si el número es 1, 2 o 3 para verificar el 30% de los casos. – philfreo

+0

No estoy seguro de cómo eso encajaría con el resto, aunque hay alrededor de 25 funciones que están por debajo del 0.5%. ¿Debería cementar o dejar el piso durante 1 y 10 o no importa asl ong ya que es consistente? – jen

4

Algo como esto debería ayudar:

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

Esto ejecutará func1() con 30.5% de probabilidad, func2() con un 40%, y func3() con 29.5%.

Probablemente podría hacerlo de forma más elegante usando un diccionario de umbrales para los punteros a la función, y un bucle que encuentra la primera entrada del diccionario con un umbral superior a randomNumber.

+0

. He intentado algo como esto, pero parece que no puedo hacer que funcione por una gran cantidad de cantidades idénticas. (mucho 0.50%) – jen

+0

Pensaba algo así como <0.50, > 0.50 && <1.0, > 1 && <1.5, pero parece que sería innecesariamente complicado si hubiera una mejor manera – jen

+1

Simplemente ajuste los umbrales a 0.5, 1.0, 1.5, 2.0 , .... Solo necesita verificar cada umbral una vez porque una vez que un umbral coincide con el otro umbral mayor no será verificado. –

0
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() 
}; 
1
// 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; 
} 

bloque de código para utilizar el

// 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); 

Simplificar código de llamada anterior con un objeto reutilizable

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); 
Cuestiones relacionadas