nick nick - 3 years ago 156
PHP Question

PHP random INT with evenly distributed order of magnitude results

PHP

rand(min, max)
between 1 and 9999 gives almost all results with 4 digits (because there are ~90% of the numbers with 4 digits). So, if I ran it 1000 times, roughly ~90% of them will probably have 4 digits.

Is there a way to generate a random INT from 1 to 9999 and that the output number have the same chance of having 1, 2, 3 or 4 digits without doing it manually?

By doing it manually I mean like this:

$digits = rand(1, 4);
$num = '';

for($i = 0; $i < $digits; $i++){
$num .= rand(0, 9);
}

$final = intval($num);

Answer Source

So, if I ran it 1000 times, roughly ~90% of them will probably have 4 digits.

That's exactly how uniform distributions work. There's no out of the box function to do what you're after, so you have to make some statistics magic.

What I'm thinking of is: generate a random number between 0 and 1. If it's between 0 and .25, generate another random number between 0 and 9. If it's between .25 and .5, generate another random number between 10 and 99, and so on and so forth. Then, you'd have 1/4 chance of getting each order of magnitude.

This will obviously have a bias towards the lower numbers though, since there are less of them. For example, 1 has a 25% / 10 = 2.5% chance, while 1001 has a 25% / 8998 = 0.00277% chance.

It'd go something like this:

<?php
$initial = rand(0, 100)/100;
if ($initial < .25) {
    $random = rand(0, 9);
}
elseif ($initial < .5) {
    $random = rand(10, 99);
}
elseif ($initial < .75) {
    $random = rand(100, 999);
}
elseif ($initial >= .75) {
    $random = rand(1000, 9999);
}
var_dump($random);

Demo

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download