Guia definitivo para gerar valores aleatórios em C

A geração de números aleatórios é um problema comum em programação, seja para testar mais rapidamente seus algoritmos, seja como parte real da solução do problema (por exemplo, para simular um cara ou coroa.

Números aleatórios (também chamados de randômicos), são gerados na linguagem C a partir do uso da função rand(). Essa função pertence a biblioteca stdlib.h, sendo que essa biblioteca também possui a função srand() e a constante RAND_MAX, ambas comumente associadas com a função rand().

Quando a função rand() é chamada ela produz um valor aleatório inteiro no intervalo de valores entre 0 e a constante RAND_MAX. A linha 5 do código abaixo mostra o uso da função rand() e também da constante RAND_MAX.

#include <stdio.h>
#include <stdlib.h> //necessario para rand()
	
int main(void) {
	printf("%i %i\n", rand(), RAND_MAX);
	return 0;
}

Se o código for executado várias vezes é possível perceber que o número aleatório mostrado é sempre o mesmo. Isso não é um problema e sim uma característica da linguagem C.

Para que cada execução do código gere um novo conjunto de valores aleatórios é necessário “plantar uma nova semente” de valores aleatórios. Isso é feito utilizando a função srand() e passando paro parâmetro para a função um valor para a semente. Esse valor normalmente é fornecido pela função time(NULL), que pertence a biblioteca time.h. A função time() se baseia no relógio do computador e retorna a quantidade de segundos passados desde 1 de janeiro de 1970. O código a seguir adiciona o uso da função srand() para gerar um valor aleatório diferente em cada execução do código.

#include <stdio.h>
#include <stdlib.h> //necessario para rand() e srand()
#include <time.h>  //necessario para time()
	
int main(void) {
	srand(time(NULL));
	printf("%i %i\n", rand(), RAND_MAX);
	return 0;
}

Simplesmente gerar valores aleatórios quaisquer é pouco útil em uma aplicação real, por exemplo, se for necessário simular a jogada de um dado de seis faces, os valores aleatórios deveriam estar no intervalo entre 1 e 6. Para isso é necessário condicionar os valores aleatórios para um intervalo e isso é feito realizando cálculos.

A linha 6 do código abaixo mostra como condicionar o valor aleatório para o intervalo entre 0 e 9. Isso porque qualquer número divido por 10, o resto dessa divisão será um número entre 0 e 9. Na linha 7 é gerado um número entre 1 e 6, simulando um dado de 6 faces. Perceba que o resultado da divisão de um número por 6 sempre resultará um número entre zero (menor valor possível) e 5 (maior valor possível). Quando é adicionado o valor 1 ao resultado, o menor valor possível passa a ser o valor 1, enquanto o maior valor possível passa a ser o valor 6, gerando valores no intervalo entre 1 e 6.

Mesmo que a função rand() gere apenas valores positivos, é possível obter valores negativos. Na linha 8 o valor é condicionado para ser um valor no intervalo entre -10 e 0. O resto da divisão de um número por 11 será um valor entre 0 e 10 e, subtraindo 10 desse resultado, é obtido como menor valor possível o valor -10 e como maior valor possível o valor 0. Na linha 9 o raciocínio é aplicado para gerar valores no intervalo entre -10 e 10.

Mesmo que a constante RAND_MAX limite os valores ao intervalo entre 0 e 32767, valores maiores do que esse limite máximo também podem ser gerados sem precisar alterar o valor da constante na biblioteca stdlib.h. Para isso basta elaborar o cálculo apropriado. Na linha 10 é gerado um valor aleatório entre 0 e 65534 a partir da soma de dois números aleatórios.

Mesmo que a função rand() apenas retorne valores inteiros, é possível utilizá-la para valores reais. Na linha 11 é gerado um número aleatório float entre 0 e 10 e com duas casas de precisão decimal. O resto da divisão de um número por 1000 é um valor entre 0 e 999, sendo que zero dividido por 100 continua sendo zero e 999 divido por 100 é 9,990000. É importante ressaltar que a função \textit{rand()} retorna um valor inteiro e que a operação de resto de divisão também obtém um valor inteiro. Com isso o numerador é um número inteiro e por isso a divisão é feita por 100.0 (número inteiro divido por outro número inteiro resultará apenas na parte inteira da divisão).

Na linha 12 é limitado os valores aleatórios ao intervalo dos números reais entre 0 e 1. Uma vez que o valor máximo que pode ser gerado pela função rand() é dado pela constate RAND_MAX, essa constante será necessária no cálculo. Como o menor valor gerado é 0, a divisão de 0 / RAND_MAX é 0 (menor valor possível). Como o maior valor gerado é RAND_MAX, o resultado da divisão de RAND_MAX / RAND_MAX é 1 (maior valor possível). A divisão de qualquer outro valor de rand() por RAND_MAX será um valor float dentro do intervalo entre 0 e 1. Observe que a constante RAND_MAX é um valor inteiro e por isso é feito um cast para transformar esse valor em seu correspondente float.

#include <stdio.h>
#include <stdlib.h>

int main(void) {
	printf("%i %i\n", rand(), RAND_MAX);
	printf("%i\n", rand()%10);
	printf("%i\n", rand()%6+1);
	printf("%i\n", rand()%11-10);
	printf("%i\n", rand()%21-10);
	printf("%i\n", rand() + rand());
	printf("%f\n", rand()%1000/100.0);
	printf("%f\n", rand()/(float)RAND_MAX);
	return 0;
}

Por fim, qualquer outra necessidade de condicionamento é uma variação das formas aqui mostradas. É importante ter em mente que o condicionamento é um cálculo aplicado a um valor inteiro positivo e limitado a um determinado valor. Levando em consideração essa limitação ao seu cálculo, é possível encontrar uma equação que condicione o valor dentro de intervalos necessários.

Share

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Esse site utiliza o Akismet para reduzir spam. Aprenda como seus dados de comentários são processados.