1

I'm messing around with some code to make a strong pseudo-random number generator using PHP. So far, I have the following.

function strongRand($bytes, $min, $max)
{
    if(function_exists('openssl_random_pseudo_bytes'))
    {
        $strong = true;
        $n = 0;

        do{
            $n = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes, $strong)));
        }
        while($n < $min || $n > $max);

        return $n;
    }
    else{
        return mt_rand($min, $max);
    }
}

This is almost perfect for me—except that all of the numbers that I generate with openssl_random_pseudo_bytes are positive. Ideally, I'd like to generate numbers from -x to +y. I have thought about maybe adding a another PRNG call to decide if a number should be positive or negative, but I'm not sure if that's the best way to go.

425nesp
  • 6,936
  • 9
  • 50
  • 61
  • What's `$bytes` doing? For an argument that's not used in some cases, it should be the last argument, but what exactly does it do / should it be doing? – Ja͢ck Jun 28 '13 at 14:05
  • `$bytes` is the number of bytes I want to get out of `openssl_random_pseudo_bytes()`. Check out the PHP doc for more info. – 425nesp Jun 29 '13 at 21:54
  • So you're saying that `strongRand(100, 1, 2)` makes sense to you? The number of bytes should be dependent on the range. – Ja͢ck Jun 29 '13 at 23:59
  • Oooh, I see what you're saying. You're right. The number of bytes *should* depend on the range. This was just a quick "sketch", if you will, of what I was doing. The part I really care about is the negative number generation. – 425nesp Jul 06 '13 at 07:22

2 Answers2

0

You could simply add another random function, we'll use rand(0,1) this will generate 0 or 1, if it's 1 $status = 1 if it's 0 $status = -1. When we return the value we do multiplication by $status:

function strongRand($bytes, $min, $max)
{
    $status = mt_rand(0,1) === 1 ? 1:-1;

    if(function_exists('openssl_random_pseudo_bytes'))
    {
        $strong = true;
        $n = 0;

        do{
            $n = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes, $strong)));
        }
        while($n < $min || $n > $max);

        return $n * $status;
    }
    else{
        return mt_rand($min, $max) * $status;
    }
}
HamZa
  • 14,671
  • 11
  • 54
  • 75
0

If you need to generate number from -x to +y, you can simply generate 4-byte uint, and:

$number = ($generated % ($x + $y + 1)) - $x
Nickolay Olshevsky
  • 13,706
  • 1
  • 34
  • 48
  • I was avoiding using the modulo operator on purpose because it's bias towards certain numbers. See: http://stackoverflow.com/questions/10984974/why-do-people-say-there-is-modulo-bias-when-using-a-random-number-generator – 425nesp May 22 '13 at 01:29