-1

I really feel ashamed to ask this question however I don't have time for revision. Also not a native English speaker, so excuse my lack of math vocabulary.

I am writing a program that requires assigning probabilities to variables then selecting one randomly.

Example:

Imagine that I have I coin, I would like to assign the probably of 70% to heads and 30% to tails. When I toss it I would like to have 70% chance that the heads appears and 30% tails.

A dumb way to do it is to create an array of cells insert the heads 70 cells and the tail in 30. Randomize them and select one randomly.

Edit 1: I also would like to point out that I am not limited to 2 variables. For example lets say that I have 3 characters to select between (*,\$,#) and I want to assign the following probably to each of them * = 30%, \$ = 30%, and # = 40%.

That's why I did not want to to use the random function and wanted to see how it was done mathematically.

Cœur
  • 37,241
  • 25
  • 195
  • 267
thedethfox
  • 1,651
  • 2
  • 20
  • 38
  • 2
    Seem to be related to http://stackoverflow.com/questions/445235/generating-random-results-by-weight-in-php – Alvin Wong Jan 10 '13 at 07:50
  • That was just an example. All the answers below will fail if I have three variable for example. probability of A = 10, B = 10 and C= 80 – thedethfox Jan 10 '13 at 07:57
  • This is not a question worth being ashamed of. The only bad question is the one not asked – Hanky Panky Jan 10 '13 at 08:01

4 Answers4

2

You want another way to do it? Most rand functions produce a decimal from [0, 1). For 30%, check produced number is less than 0.3

Though note, if you actually test the perceived "randomness", it's not really random..

In PHP, you can use rand(0, 99) (integer instead of double, 30 instead of 0.3). PHP rand function is a closed interval (both inclusive)

function randWithWeight($chanceToReturnTrue) { // chance in percent
    return rand(0, 99) < $chanceToReturnTrue;
}

Edit: for the note about perceived randomness. Some math since you say you're coming from math... Generate numbers from 0-99, adding them to an array. Stop when the array contains a duplicate. It usually takes about ~20 passes (I'm getting 3-21 passes before duplicate, 10+ tries). So it's not what you'd expect as "random". Though, (I know I'm going off track), take a look at the birthday problem. It is "more random" than it seems.

Raekye
  • 5,081
  • 8
  • 49
  • 74
  • Not sure what you're getting at with the "perceived randomness" bit; surely any distinction between pseudorandom/random is irrelevant for the OP's question. – bnaul Jan 10 '13 at 07:52
  • He's coming from a math side, may be wanting a "better" random generator. – Raekye Jan 10 '13 at 07:53
  • +1. However this will fail if I have 3 variables. Two of which have a similar probability – thedethfox Jan 10 '13 at 08:24
1

If you want 30% probability just do

if(rand(1,100) <= 30){
    // execute code
}
Alvin Wong
  • 12,210
  • 5
  • 51
  • 77
David
  • 34,836
  • 11
  • 47
  • 77
1

One way would be

$r=rand(1,100);
if($r<70)
{
   echo "Head";
}
else
{
   echo "Tail";
}
Hanky Panky
  • 46,730
  • 8
  • 72
  • 95
  • +1. However this will fail if I have 3 variables. Two of which have a similar probability – thedethfox Jan 10 '13 at 08:15
  • 1
    Thanks @thedethfox but the possibility of 3 variables was not mentioned in your original question. And this was just a guide in right direction, not the ultimate solution. Cheers :) – Hanky Panky Jan 10 '13 at 08:56
1

Here is a simple function to calculate weighted rand:

<?php
function weightedRand($weights, $weight_sum = 100){
    $r = rand(1,$weight_sum);
    $n = count($weights);
    $i = 0;
    while($r > 0 && $i < $n){
        $r -= $weights[$i];
        $i++;
    }
    return $i - 1;
}

This function accepts an array. For example array(30,70) will have 30% chance getting 0 and 70% chance getting 1. This should work for multiple weights.

Its principle is to subtract the generated random number by the weight until it gets less than or equal to zero.

Demo with 30%:70%
Demo with 20%:30%:50%

Alvin Wong
  • 12,210
  • 5
  • 51
  • 77