Mlabuit
Mlabuit

Reputation: 75

Value probability based on percentage

Is there a way to extract a value based on a percentage?

Value probability:
Bad: 1%
Normal: 29%
Good: 70%

var move ["bad","normal","good"];

A simple conditional statement:

if (move == "bad") {
bad_move = "That's a bad move!";
} else if (move == "normal") {
normal_move = "Classic move!";
} else {
good_move = "Amazing move!";
}

Then, is PHP better than Javascript for this kind of problem?

Upvotes: 4

Views: 1123

Answers (2)

SimpleJ
SimpleJ

Reputation: 14778

You could write a function that samples values with given probability percentages:

function weightedSample(pairs) {
  const n = Math.random() * 100;
  const match = pairs.find(({value, probability}) => n <= probability);
  return match ? match.value : last(pairs).value;
}

function last(array) {
  return array[array.length - 1];
}

const result = weightedSample([
  {value: 'Bad', probability: 1},
  {value: 'Normal', probability: 29},
  {value: 'Good', probability: 70}
]);

console.log(result);

I can't say if PHP would be better. This kind of problem shouldn't be any more/less difficult in PHP. Which you should use (JS or PHP) really depends on whether or not the function should be run on the server or client.

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386670

I suggest to use a continuous check of the probability and the rest of the random number.

This function sets first the return value to the last possible index and iterates until the rest of the random value is smaller than the actual probability.

The probabilities have to sum to one.

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,
    move = ["bad", "normal", "good"],
    probabilities = [0.01, 0.29, 0.7],
    count = {},
    index;

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

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

console.log(count);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 0

Related Questions