2012-01-16 1 views
17

Je suis un peu confus sur la façon de générer des valeurs entières avec des probabilités. être clair, par exemple,générer des entiers aléatoires avec des probabilités

j'ai quatre nombres entiers avec leurs valeurs de probabilité: 1 | 0,4, 2 | 0,3, 3 | 0,2, 4 | 0,1

Comment générer ces quatre numéros tenant compte de leur probabilités?

La mise en œuvre javascript serait appréciée.

+0

Si vous voulez connaître beaucoup de détails techniques sur la façon de le faire rapidement, cela est une excellente ressource. Pour faire un choix pondéré parmi 4 choix, c'est totalement inutile cependant. http://www.keithschwarz.com/darts-dice-coins/ –

+0

Voir aussi http://stackoverflow.com/questions/3094873 – Lucas

Répondre

28

Voici une astuce utile :-)

function randomWithProbability() { 
    var notRandomNumbers = [1, 1, 1, 1, 2, 2, 2, 3, 3, 4]; 
    var idx = Math.floor(Math.random() * notRandomNumbers.length); 
    return notRandomNumbers[idx]; 
} 
+2

Corriger la direction, il suffit de créer dynamiquement 'notRandomNumbers' (étant donné les nombres et leur poids/probabilité) et c'est la solution idéale à mon avis. –

+0

Nice! Merci. Cela ressemble à ce dont j'ai besoin. – Headshota

+0

@ShadowWizard: oui, je l'ai fait simple pour la clarté :-) –

21

Une approche simple peut être naïve:

function getRandom(){ 
    var num=Math.random(); 
    if(num < 0.3) return 1; //probability 0.3 
    else if(num < 0.6) return 2; // probability 0.3 
    else if(num < 0.9) return 3; //probability 0.3 
    else return 4; //probability 0.1 
}

+0

Et si deux nombres avaient la même probabilité? :-) –

+1

la logique restera la même. voir l'édition. – bhups

8

solution plus souple basée sur @bhups réponse. Cela utilise le tableau des valeurs de probabilité (poids). La somme des éléments 'de poids doit être égal à 1.

var weights = [0.3, 0.3, 0.3, 0.1]; // probabilities 
var results = [1, 2, 3, 4]; // values to return 

function getRandom() { 
    var num = Math.random(), 
     s = 0, 
     lastIndex = weights.length - 1; 

    for (var i = 0; i < lastIndex; ++i) { 
     s += weights[i]; 
     if (num < s) { 
      return results[i]; 
     } 
    } 

    return results[lastIndex]; 
}; 
2

Je suggère d'utiliser un contrôle continu de la probabilité et le reste du nombre aléatoire.

Cette fonction définit d'abord la valeur de retour au dernier index possible et itère jusqu'à ce que le reste de la valeur aléatoire soit inférieur à la probabilité réelle.

Les probabilités doivent totaliser un.

function getRandomIndexByProbability(probabilities) { 
 
    var r = Math.random(), 
 
     index = probabilities.length - 1; 
 

 
    probabilities.some(function (probability, i) { 
 
     if (r < probability) { 
 
      index = i; 
 
      return true; 
 
     } 
 
     r -= probability; 
 
    }); 
 
    return index; 
 
} 
 

 
var i, 
 
    probabilities = [0.4, 0.3, 0.2, 0.09, 0.01 ], 
 
    count = {}, 
 
    index; 
 

 
probabilities.forEach(function (a) { count[a] = 0; }); 
 

 
for (i = 0; i < 1e6; i++) { 
 
    index = getRandomIndexByProbability(probabilities); 
 
    count[probabilities[index]]++ 
 
} 
 

 
console.log(count);

Questions connexes