[PHP] Random Number Problem

Status
Not open for further replies.

Mr Happy

Active Member
4,093
2009
2,572
0
Basically I want to generate a Random number but increase the chances of lower numbers appearing more.

if I just use mt_rand(1, 1000) the chances of getting the number 1 is the same as 468 which is the same as 1000.

I want to increase the chances of lower numbers appearing.

This poor way shows what I mean

PHP:
if (mt_rand(1, 2) == 1)   // 50-50 chance
{
	mt_rand(1, 10);
}
else if (mt_rand(1, 2) == 1)
{
	mt_rand(10, 100);
}
else
{
	mt_rand(100, 1000);
}

So the chance of the number between 1 and 10 is higher than between 10 and 100 which is higher than 100 and 1000.

It's still pretty crap though as the chance of getting 124 is the same as 975 (not to mention it's generating upto 5 times to get one result).

I want a gradual increase in chance. I don't even know the mathematical term. Searching "php random sliding scale" gives random image scripts and "php random heavy slide" gives articles on the difference between rand() and mt_rand()

Can anyone help with an fast efficient function or even tell me the mathematical term for what I want to make searching easier?
 
31 comments
PHP:
$num = (time() & 1) ? mt_rand(1, 10) : mt_rand(1, 1000);
Or Maybe

PHP:
$num = (time() & 1) ? mt_rand(1, 10) : mt_rand(1, mt_rand(10, 1000));
 
a bit more complicated, but you get the idea. Sorry, i dont know php, but you can of course see the logic.

PHP:
static void DoWork()
        {
            Random rnd = new Random(5000);
            string output = string.Empty;

            int num1 = rnd.Next();
            int num2 = num1;
            num1 = rnd.Next();

            if (num1 > num2)
            {
                for (int i = 0; i < 5; i++) // 5 chances to be smaller than previous.
                {
                    num1 = rnd.Next();
                    if (num1 < num2)
                        break;
                }
            }

            output += num1.ToString() + Environment.NewLine;
        }
 
PHP:
if(substr(time(),0,-1) > 7)
{
    //LOWER NUMBER (Chances are 7/10) of being lower
}else
{
   //Higher
}

But the problem with the above is it will be lower for every 7 out of 10 seconds.
 
PHP:
function doWork()
{
    $rnd = rand(0,5000);

    $num1 = $num2 = $rnd+1;


    if(($num1+1) > $num2)
    {
        for($i=0;$i<5;$i++)
        {
            $num1 = $rnd+1;
        }
    }
    return $num1;
}

Translated version for JayFella.
 
why am i the only one writing the whole thing :( makes me look bloated :((

My 1 line of code is the whole thing :'(. It has 50% chance of generating a number between 1 and 10 and 50% chance of generating one between 1 and 1000 (using the 1st one). And its fast because its only 1 binary AND operation, one if-else and one rand().
 
Ok so these are all far superior on what I used as an example but their's no way of doing this so
1 is bigger than 2 which is bigger than 3 which is bigger than 4 which is bigger than 5 .....

I asked a friend (Phd Mathematical Student) after making this topic and said I need to set up a matrix and add a curve or something where x=0 and y=1000 where points were picked but I didn't really understand what he was saying.

Anyway it's not that important as long as it's roughly weighted which we've all got. Just though their was a maths way. Maths is seriously not my strong point.

See while Hyperz way is fast the chances of getting 116 are the same as 959 which isn't exactly what I want.


Thanks for all the quick replies.
 
Oh I didn't think of a matrix, that would actually make it fairly effective and also easy to implement. I'll write another example with once I finish my coffee.
 
Clocked it bitches:

Test Case:
PHP:
$up = $down = 0;
while(true)
{
   if(abs((rand()%150)-50) < 50)
   {
      $up++;
   }else
   {
      $down++;
   }
   if( ($up + $down) == 1000){ break;} //500 loops for the test case
}

echo $up . '/' . $down;

This gives results where the lower number is more likley.

run it keep refreshing and it will tell you the chances of the lower over the higher number.

So what you actually want is

PHP:
$number = abs((rand()%150)-50); // 0-100
 
Not the best implementation of what your friend suggest (I do suck at math) but this should work. As you generate more number the chance of getting a bigger number will increase.

PHP:
// Setup
$min = 10;
$max = 1000;
$step = 0;
$index = 0;
$matrix = array();

// curve
for ($i = 0; $i < $max; $i++)
{
    $matrix[i] = $min + $step;
    
    if ($i & 1 && ($min + $step) < $max)
    {
        $step = ($step + 3 > $max - $min) $max - $min : $step + 3;
    }
}

// generate the next random number
function GetNext()
{
    return ($index < count($matrix)) ? rand(1, $matrix[$index++]) : rand(1, $matrix[$index]);
}
This actually needs a class but I'm sure that's no problem for you :). (didn't test it btw)
 
Don't work dood, just returns 1 constantly.

PHP:
// Setup
$min = 10;
$max = 1000;
$step = 0;
$index = 0;
$matrix = array();

// curve
for ($i = 0; $i < $max; $i++)
{
    $matrix[$i] = $min + $step; //Fix i to $i
    
    if ($i & 1 && ($min + $step) < $max)
    {
        $step = (($step + 3) > ($max - $min)) ? ($max - $min) : ($step + 3); //Wraped calculations
    }
}

// generate the next random number
function GetNext()
{
    return ($index < count($matrix)) ? rand(1, $matrix[$index++]) : rand(1, $matrix[$index]);
}  
echo GetNext(); //Returns 1

-

Just thought of another way to do it!

PHP:
$perecntage = 70; //70% to lower side

$direction = (rand(0,100) < $percentage /  ? 'lower' : 'hither'); //The chances of 0 - 100 is 70%
$number = ($direction == 'lower' ? rand(0,$percentage) : /*higher*/ rand($percentage,100));

This would work to get less than 70 most of the time 70%.
 
Don't wrap my calculations and expect to live <_<.
Anyway, fixed the obvious:

PHP:
<?php

$min = 10;
$max = 1000;
$step = 0;
$index = 0;
$matrix = array();

for ($i = 0; $i < $max; $i++)
{
    $matrix[$i] = $min + $step;
    
    if ($i & 1 && ($min + $step) < $max)
    {
        $step = ($step + 3 > $max - $min) ? $max - $min : $step + 3;
    }
}

function GetNext()
{
    global $matrix, $index;
    return ($index < count($matrix)) ? rand(1, $matrix[$index++]) : rand(1, $matrix[$index]);
}

?>
PS: PHP is shyte.

Edit:
Your other way doesn't do what he wants it to do.
 
yea i know, the first one does using abs.

erm for some reason yours just keeps bringing back an average of 5, 1,8,9,7,8,7,9... it never gets higher then 10 and for a max of 1K it should do.

erm

PHP:
function getRand()
{
    $check = rand(0,100);
    if($check < 70) //This means that 50% of the time, the below line will execute.
    {
        $check = rand(0,50);
        //Because the chances of the above being true are 70/100, this will execute.
        //And If it does not get to here then the $check will be within 70-100.
    }
}

echo getRand(); //Test.

But i still think my other one is good aswell.
 
Well obviously if you keep refreshing it'll stay at a low number since the matrix and index gets rebuild every time. Put GetNext() in a for loop with 1000 irritations and you'll see it does exactly what it's supposed to do. Also, your methods aren't doing what he wants it to do. Otherwise my 1st example could be used which is still the fastest.
 
Well obviously if you keep refreshing it'll stay at a low number since the matrix and index gets rebuild every time. Put GetNext() in a for loop with 1000 irritations and you'll see it does exactly what it's supposed to do. Also, your methods aren't doing what he wants it to do. Otherwise my 1st example could be used which is still the fastest.
lol that's why it wasn't working for me either. I don't understand it but when it's put in a loop it does seam to work as it's meant to. Correct me if I'm wrong as I don't understand matrix but doesn't this mean that you have to run all 1000 and pick one of the 1000 at random to then get a result?

By the way for the original purpose it's not critical that this is worked out fully but I am finding it a huge learning experience which is probably more important.

@litewarez. That % thing is nice. Not exactly what I was after but I like how you did it.
 
Well lets walk threw it:

abs() is a function used to set teh Absolute value of something, so that the number is not a negative but always a positive.

rand() with no parameters creates a number from 0 to the highest available number for that operating system.

the % is an Arithmetic Modulus operator what it does is return the remainder of A devided by B.

and the -50 you know.

heres a visual example.

PHP:
$rand = 1045676;
$mod = ($rand % 150); //basically, how many times 150 goes into 1045676 and return the remainder.
//$mod is 26

$mod = $mod-50; // -24, but after abs() becomes 24; witch is a positive

//And all together
$number = abs(  (  rand()  %  150  )  -50  );;

Hope this helps dood, its a sexy and small way xD

Do i win ??
 
lol that's why it wasn't working for me either. I don't understand it but when it's put in a loop it does seam to work as it's meant to. Correct me if I'm wrong as I don't understand matrix but doesn't this mean that you have to run all 1000 and pick one of the 1000 at random to then get a result?

By the way for the original purpose it's not critical that this is worked out fully but I am finding it a huge learning experience which is probably more important.

@litewarez. That % thing is nice. Not exactly what I was after but I like how you did it.

Maybe you should explain again what you want it to do. I thought you wanted to generate a random numbers that with each generated number have a higher probability of generating a bigger value. Since your friend suggested a matrix with a curve etc.
 
Status
Not open for further replies.
Back
Top