 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);
`````` ishegg

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