views:

119

answers:

2

I've the following code in PHP which works fine (returns more or less 10 results each time it runs):

function GetAboutTenRandomNumbers()
{
    $result = array();

    for ($i = 0; $i < 240; $i++)
    {
     if (Chance(10, 240) === true)
     {
      $result[] = $i;
     }
    }

    echo '<pre>';
    print_r($result);
    echo '</pre>';

    return $result;
}

And the Chance() function goes as follows:

function Chance($chance, $universe = 100)
{
    $chance = abs(intval($chance));
    $universe = abs(intval($universe));

    if (mt_rand(1, $universe) <= $chance)
    {
     return true;
    }

    return false;
}

Now, I want to randomly split those 10 (on average) results in the 4 following segments:

  1. the first one having a probability of 10% * 10 = 1
  2. the second one having a probability of 20% * 10 = 2
  3. the third one having a probability of 30% * 10 = 3
  4. the fourth one having a probability of 40% * 10 = 4

As you can see the sum of all segments (1 + 2 + 3 + 4) equals 10, so I've coded the following function to do this.

function GetAboutTenWeightedRandomNumbers()
{
    $result = array();

    // Chance * 10%
    for ($i = 0; $i < 60; $i++)
    {
     if (Chance(10 * 0.1, 240) === true)
     {
      $result[] = $i;
     }
    }

    // Chance * 20%
    for ($i = 60; $i < 120; $i++)
    {
     if (Chance(10 * 0.2, 240) === true)
     {
      $result[] = $i;
     }
    }

    // Chance * 30%
    for ($i = 120; $i < 180; $i++)
    {
     if (Chance(10 * 0.3, 240) === true)
     {
      $result[] = $i;
     }
    }

    // Chance * 40%
    for ($i = 180; $i < 240; $i++)
    {
     if (Chance(10 * 0.4, 240) === true)
     {
      $result[] = $i;
     }
    }

    echo '<pre>';
    print_r($result);
    echo '</pre>';

    return $result;
}

The problem is I've run the GetAboutTenWeightedRandomNumbers function dozens of times and the result is much more lower than the result returned by the GetAboutTenRandomNumbers function. I'm sure that I'm making a fundamental math mistake, I suspect where but I don't know how to solve it.

+2  A: 

If you're expecting DoIt_02() to return about the same number of results as DoIt_01(), then yeah, you're making a fundamental math mistake. Your sections' probability weights summing to 10 means nothing because the weighted chances aren't applied to the entire 0..240 set. It would return similar results if you ran each restricted probability on 0..240 instead of 0..59, 60..119, etc.

Incidentally, your Chance() function is slightly off in that, to get the probabilities you seem to be trying for, it should be either mt_rand(1, $universe) <= $chance or mt_rand(0, $universe - 1) < $chance.

chaos
Thank you, specially for the Chance() warning - it didn't noticed until you mentioned it.
Alix Axel
+3  A: 

Indeed you are!

In your second pass, you're giving it 60 values each pass, instead of 240, so you'll get about a quarter of the expected values in that pass. Run each to 240 and use a modulo 60 to get the range of values you're looking for in each loop.

Eric
Thanks, seems to be working like it should now. =)
Alix Axel