5

In other languages I would generate it in parts and store it in a string but with PHP you can't choose the data type so that doesn't work, its automatically set as an integer then can only store up to the maximum integer size.

Is there any solution to this?

Tom
  • 51
  • 2
  • Using the GMP extension, [`Alphabet::convert(\random_bytes(32), Alphabet::BYTE, Alphabet::DECIMAL)`](https://github.com/delight-im/PHP-BaseConvert) should do the trick. – caw Aug 26 '19 at 02:35

5 Answers5

3

Yes, you can obtain some random data (e.g. from /dev/urandom, or openssl_random_pseudo_bytes).

Then convert the data into its decimal representation, using e.g. bcmath or gmp. See this answer on how to do that.

Community
  • 1
  • 1
Artefacto
  • 96,375
  • 17
  • 202
  • 225
2

I had the same problem. I had a function that needs to generate a random number from 0 to 2^32-1 (representing it as a 8-digit hexadecimal string). mt_rand() only generates numbers from 0 to 2^31-1.

This fails:

return hexdec(mt_rand(0,4294967295));

I resolved this with a single line of code:

return sprintf("%04X%04X", (mt_rand(0,65535)), (mt_rand(0,65535)));

What this does is exactly what you suggested, breaking the randomization into parts. It generates two random numbers, each from 0 to 2^16-1 (65,535) (hex 0000 to FFFF), and then concatenates them together using sprintf to zero-pad the results as hexadecimal strings.

Every single number from 0 to 2^32-1 (hex 00000000 to FFFFFFFF) is possible. If you wanted a 48-bit random hexadecimal number (hex 000000000000 to FFFFFFFFFFFF), you could extend this like so:

return sprintf("%04X%04X%04X", (mt_rand(0,65535)), (mt_rand(0,65535)), (mt_rand(0,65535)));

This works for me!

chriv
  • 752
  • 1
  • 7
  • 18
1

mt_rand(0, 10000) will generate four digits of your random number. Call it several times, concatenate the results:

mt_rand(0, 10000) . mt_rand(0, 10000) . mt_rand(0, 100) - for 10 digits long number.

This has numerous issues, but it might be good enough for your particular use case.

Roman Zenka
  • 3,514
  • 3
  • 31
  • 36
0

What I would do is something like this:

function getBigRandom($length, $space = '0123456789', $trim = true) {
    $str = '';
    $spaceLen = strlen($space);
    for ($i = 0; $i < $length; $i++) {
        $str .= $space[mt_rand(0, $spaceLen - 1)];
    }
    if ($trim) {
        $str = ltrim($str, '0');
    }
    return $str;
}

Usage:

$random = getBigRandom(15); // Generate up to a 15 digit random number

The random distribution should be fairly even, since each decimal place has an equal probability of being every type of value... Calling it with the default params will generate a number. If you want to generate a string (salt, etc), you can do:

$random = getBigRandom(
    128,
    'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 
    false
);
ircmaxell
  • 163,128
  • 34
  • 264
  • 314
-3
$i = (int) $i;

You can declare type.

Dejan Marjanović
  • 19,244
  • 7
  • 52
  • 66
  • in my opinion this isnt type declaration its more type casting – streetparade Dec 24 '10 at 00:06
  • I'm not sure what this has to do with generating random numbers larger than the `int` type can handle... – ircmaxell Dec 24 '10 at 04:01
  • 1
    Please add some explanation to your answer such that others can learn from it. As far as I see, casting a variable to an integer does not generate random numbers – Nico Haase Jun 03 '20 at 08:59