After I was pointed out, that it would be better to use the PHP function mt_rand() instead of rand() for generating random numbers (because mt_rand() should be more accurate), I decided to investigate on that statement. But at first, where is the difference between rand() and mt_rand()?
By use of mt_rand() you can generate random numbers just like with the rand() function. The function call also looks equal on both functions. Though the PHP documentation says mt_rand() is up to 4-times faster and would be create more random/arbitrary numbers. By implication this would mean, that the rand() function creates inaccurate random numbers.
I was not aware of this problem, but after some googleing I discovered that there are a lot of people who think that mt_rand() is the better function. However I had to notice that most of the contributions which complain that rand() is not clean are a “little older”.
Often cited in support of the arguments is an article of Dog.net Development, which visualizes the alleged disadvantages of rand() in contrary to mt_rand(). The already mentioned assertion, rand() would not create random numbers correctly, is claimed by the Dog.net Development author by a short but effective PHP script. Because I wanted to comprehend the asserted problem, I’ve written a similar script.
<?php header("Content-type: image/png"); $img = imagecreatetruecolor(256, 256) or die("Error while creating the graphic."); $white = imagecolorallocate($img, 255, 255, 255); for ($x=0; $x<256; $x++) { for ($y=0; $y<256; $y++) { if (mt_rand(0,1) === 1) { imagesetpixel($img, $x, $y, $white); } } } imagepng($img); imagedestroy($img); ?>
The script creates a 256×256 pixel image. Wherein for each pixel, a random number between 0 and 1 is generated. If the number is a 1 the pixel is colored white else the pixel is colored black.
Dog.net ran this algorithm once with mt_rand () and once with the rand () and received the following two graphics (click to enlarge):
Here it can be seen why many are denouncing the rand() function. On the image that was created using the rand() function a pattern is clearly discernible. This would mean that the random numbers from rand () are not truly random. But…
…at this point I would like to confront my observations. I said earlier on, that the most accusatory articles are a bit dated. So there was enough time to improve the rand() function. Therefore I thought it would be a good idea to recreate the script of Dog.net and see what happens. And lo and behold …
(Picture created using rand())
(Picture created using mt_rand())
…miraculously both functions appear to work very well. All that remains is to verify whether mt_rand () is at least faster than rand(), as it was claimed. For this I have written another small script.
<?php $start = microtime(true); for ($i=0; $i<1000000; $i++) { $random = mt_rand(0,1); } $end = microtime(true); $runtimeMtRand= $end - $start; $start = microtime(true); for ($i=0; $i<1000000; $i++) { $random = rand(0,1); } $end = microtime(true); $runtimeRand = $end - $start; echo "Runtime mt_rand(): ".$runtimeMtRand." seconds!"; echo "Runtime rand(): ".$runtimeRand." seconds!"; ?>
And at this point, then also follows the second surprise. The script returned the following result:
Runtime mt_rand(): 1.033802986145 seconds! Runtime rand(): 1.1012179851532 seconds!
mt_rand() is not 4-times fast as rand(). It is not even 2-times as fast. So in my eyes there is no reason to switch from the rand() function to the mt_rand() function.
What do you think? Could I convince you?
Best regards,
Raffi
The apparent visual randomness of a field of dots is not an adequate test for randomness. There are plenty of ways that data can be non-“random” that won’t readily manifest themselves visually in this test.
Since PHP 7.1, rand has become an alias of mt_rand, so it’s the same function now if you use the latest version of PHP
Just asking but could it be that in the first test of the rand(); function the fact the image was 256×256 had some impact… multiples of 2 are after all relevant in terms of processing and whatnot and are reflected in architecture… were the image 234×271 or better yet two primes then it might have been a different kettle of fish….. point accepted though it wasn’t pseudo random… which is clearly poor testing from the get go…who let this slip in?
i look for fast rand, i find code: num256 = mt_rand() & 255
rand() is not good, after ~32.000 iterations repeat numbers (php 5.5.12).
Hello Raffi, I’m not sure what do you mean by a “better” random function. Both are unsafe http://phpsecurity.readthedocs.org/en/latest/Insufficient-Entropy-For-Random-Values.html.
Hey Lukasz,
thank you for the link. The article is very interesting!