Rand vs mt_rand PHP

Porquê usar mt_rand() ao invés de rand() no PHP


Todo programador PHP gosta de usar um rand(0,10000) nos seus códigos… Mas existe um jeito muito melhor de fazer isso: mt_rand(0,10000).

Nesse artigo vou explicar porquê.

A função rand() é muito mais antiga do que o mt_rand(), e já caiu no gosto dos programadores, mas tem sérios riscos de segurança. Um Gerador de números pseudoaleatórios precisa ter um certo nível de entropia, ou “desordem”, ou seja, uma verdadeira aleatoriedade. A entropia do rand() é muito baixa, fazendo com que, tendo uma lista de números gerados por ele, seja possível adivinhar os próximos números que serão gerados.

O pessoal do Techno.dev fez um teste muito interessante. Usando esse código, eles geraram uma imagem com pontos posicionados aleatóriamente pelo rand() e pelo mt_rand(). Veja o resultado:

$img = imagecreatetruecolor(512,512);
$i = 0;
while($i < 512*512) {
imagesetpixel(
$img,
mt_rand(0,512),
mt_rand(0,512),
imagecolorallocatealpha(
$img,
mt_rand(0,255),
mt_rand(0,255),
mt_rand(0,255),
mt_rand(0,127)
)
);
$i++;
}
imagepng($img,”mt_rand.png”);
imagedestroy($img);
$img = imagecreatetruecolor(512,512);
$i = 0;
while($i < 512*512) {
imagesetpixel(
$img,
rand(0,512),
rand(0,512),
imagecolorallocatealpha(
$img,
rand(0,255),
rand(0,255),
rand(0,255),
rand(0,127)
)
);
$i++;
}
imagepng($img,”rand.png”);
imagedestroy($img);

rand()

mt_rand()

De acordo com o Tecnho.dev, no Linux os resultados foram satisfatoriamente similares, porém no Windows a entropia do rand() foi muito baixa.

Há ainda um teste na documentação oficial do rand() no php.net que demonstra claramente a baixa entropia do mesmo:

$r = array(0,0,0,0,0,0,0,0,0,0,0);
for ($i=0;$i<1000000;$i++) {
  $n = rand(0,100000);
  if ($n<=10) {
    $r[$n]++;
  }
}
print_r($r);

 

Resultado:

Array
(
[0] => 31
[1] => 0
[2] => 0
[3] => 31
[4] => 0
[5] => 0
[6] => 30
[7] => 0
[8] => 0
[9] => 31
[10] => 0
)

Dentro desse escopo, apenas múltiplos de 3 foram gerados, e note que os valores são sempre 30 ou 31!

Agora substitua rand() por mt_rand() e veja a diferença:

Array
(
[0] =&gt; 8
[1] =&gt; 8
[2] =&gt; 14
[3] =&gt; 16
[4] =&gt; 9
[5] =&gt; 11
[6] =&gt; 8
[7] =&gt; 9
[8] =&gt; 7
[9] =&gt; 7
[10] =&gt; 9
)

Agora sim, muito mais aleatório!

Não apenas mt_rand() é mais rápido, como também muito mais eficiente.

Razões para usar mt_rand():

  • Foi criado para substituir o rand()
  • Tem uma performance um pouco melhor
  • Melhor aleatoriedade: mt_rand(219937− 1), contra rand(232)
  • A partir do PHP 7.1, a função rand() propriamente dita deixou de existir, e virou um alias de mt_rand()

Se você precisa gerar um número aleatório sem muita importância e segurança não é um grande risco, pode usar rand() sem neura, mas se você precisa de números verdadeiramente aleatórios, use o mt_rand(), pois além de tudo, tem uma performance melhor.

 

Fontes:
http://stackoverflow.com/questions/28760650/difference-between-mt-rand-and-rand
http://php.net/manual/en/function.rand.php#73730


Tag: , , ,