可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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?
回答1:
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.
回答2:
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.
回答3:
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.
回答4:
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
回答5:
Use this for strings of a certain length with both letters and numbers. Tested.
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, 25);
$data = strtoupper($alpha[$item]);
break;
}
$result .= $data;
}
return $result;
}
回答6:
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.
回答7:
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.
回答8:
How about this:
function random($len)
{
static $track = [];
$min = 1 . str_repeat(0, $len - 1);
$max = str_repeat(9, $len);
$num = mt_rand($min, $max);
// was this number generated before?
if (in_array($num, $track))
{
// try again
return random($len);
}
return $track[] = $num;
}
Keeping track of generated numbers via static variable (which is initiated once) will prevent generating the same number twice, unless you go through the whole range, in which case you get stuck in infinite loop.
For example:
for ($i = 0; $i < 10; $i++)
{
random(1);
}