问题描述:

I'm trying to create a function using mt_rand() in order to generate a truly random number, since rand() just isn't suffice.

The problem is I need to pre-define the length of the number, say I need a 10 digit random number.

Anyway, I've been messing around and this is what I've come up with:

`function randomNumber($length) {`

$min = str_repeat(0, $length-1) . 1;

$max = str_repeat(9, $length);

return mt_rand($min, $max);

}

In theory that should work (as far as I can tell), but it doesn't. The length is completely random and it also throws out negative values.

Any ideas?

Unless you have one of those quantum-static thingies, you can't get a truly random number. On Unix-based OSes, however, `/dev/urandom`

works for "more randomness", if you really need that.

Anyway, if you want an n-digit number, that's exactly what you should get: n individual digits.

```
function randomNumber($length) {
$result = '';
for($i = 0; $i < $length; $i++) {
$result .= mt_rand(0, 9);
}
return $result;
}
```

The reason your existing code isn't working is because `0000...01`

is still `1`

to `mt_rand`

, and also that `mt_rand`

's range isn't infinite. The negative numbers are integer overflows.

Short and sweet:

I'm assuming only legitimate numbers, not strings like 00010. Try useing the size of your number to be:

```
$min = pow(10, $length - 1) ;
$max = pow(10, $length) - 1;
return mt_rand($min, $max);
```

The only one that doesn't work is when length is 1, a single digit number '0' won't be a possible value to be returned.

You shouldn't start with the length constraining the random numbers. Rather accumulate a long enough output, then cut it to the right length:

```
while (strlen($value) < $length) {
$value .= str_pad(mt_rand(00000, 99999), 5, "0", STR_PAD_LEFT);
}
// as pairs of five were added before, eventually remove some again
return substr($value, 0, $length);
```

The padding should be there, because even zeros are randomly generated and should be retained.

```
function randomNumber($length) {
$min = 1 . str_repeat(0, $length-1);
$max = str_repeat(9, $length);
return mt_rand($min, $max);
}
```

you have your concat 1 in the wrong spot, your range is this for $length=2: {01,99} - sometimes its 01-09, that is represented as 1-9 not 01-09. Just start from 10: {10,99} will be your range.

Thank you for this example. I have added letters to the simplicity. This works great for me as I am using this with additional tokens for validation.

```
protected function randomToken($length = 4, $result='') {
for($i = 0; $i < $length; $i++) {
$case = mt_rand(0, 1);
switch($case){
case 0:
$data = mt_rand(0, 9);
break;
case 1:
$alpha = range('a','z');
$item = mt_rand(0, 26);
$data = strtoupper($alpha[$item]);
break;
}
$result .= $data;
}
return $result;
}
```

Here is what I'm using:

```
function random_number($length)
{
return join('', array_map(function($value) { return $value == 1 ? mt_rand(1, 9) : mt_rand(0, 9); }, range(1, $length)));
}
```

One line, nice and simple! The number will never start with 0 and allows 0 at any other place.

```
function randomNDigitNumber($digits)
{
$returnString = mt_rand(1, 9);
while (strlen($returnString) < $digits) {
$returnString .= mt_rand(0, 9);
}
return $returnString;
}
```

The first line ensures that no "0" precedes any number, for instance values like 012, 0598... will be discarded, the rest is easy