Projeto de Algoritmos

Números aleatórios

A biblioteca stdlib define a função  rand  (abreviatura de random).  Esta função gera números aleatórios (ou melhor, pseudoaleatórios). Mais precisamente, cada chamada da função produz um

número aleatório no intervalo fechado [0,RAND_MAX].

A constante RAND_MAX está definida no arquivo-interface stdlib.h.

Eric Roberts (The Art and Science of C) escreveu uma biblioteca random, que torna mais amigável o uso da função rand.  Exibiremos abaixo as funções da biblioteca.

Exercícios preliminares

  1. [Roberts]  O seguinte programa promete simular uma jogada de um dado de 6 faces. Qual o defeito do programa?
    int RolaDado (void) {
        int r;
        r = rand ();
        if (r < RAND_MAX / 6) return 1;
        else if (r < RAND_MAX * 2 / 6) return 2;
        else if (r < RAND_MAX * 3 / 6) return 3;
        else if (r < RAND_MAX * 4 / 6) return 4;
        else if (r < RAND_MAX * 5 / 6) return 5;
        else return 6;
    }
    
  2. [Roberts. Sutil]  O seguinte programa promete simular uma jogada de uma moeda. Qual o defeito do programa?
    char *RolaMoeda (void) {
        int r;
        r = rand () % 2;
        if (r == 1) return "cara";
        else return "coroa";
    }
    

Reais e inteiros aleatórios

Eis como rand pode ser usada para gerar um número real aleatório num dado intervalo:

#include <stdlib.h>

// A função RandomReal devolve um número real 
// (pseudo)aleatório no intervalo semi-aberto
// [low, high). O código foi copiado da biblioteca
// random de Eric Roberts.

double RandomReal (double low, double high)
{
    double d;

    d = (double) rand () / ((double) RAND_MAX + 1);
    return low + d * (high - low);
}

Eis como se pode gerar um número inteiro aleatório num dado intervalo:

// A função RandomInteger devolve um inteiro 
// (pseudo)aleatório entre low e high inclusive,
// ou seja, no intervalo fechado [low,high].
// Estamos supondo que high-low <= RAND_MAX.
// O código foi copiado da biblioteca random 
// de Eric Roberts.

int RandomInteger (int low, int high)
{
    int k;
    double d;

    d = (double) rand () / ((double) RAND_MAX + 1);
    k = d * (high - low + 1);
    return low + k;
}

Como a função faz o serviço? Primeiro, transforma o número inteiro aleatório produzido por rand em um número real no intervalo [0,1). Depois, transforma esse número real em um número inteiro no intervalo [0,high-low+1). Finalmente, transforma esse número em um inteiro no intervalo [low,high].

Se highlow for maior que RAND_MAX, o função RandomInteger nunca produz o número high.  Por exemplo, se RAND_MAX = 99 então

RandomInteger (int 0, int h)  ≤  h-1

para todo h > 99.

Exercícios

  1. No código de RandomInteger, suponha que a linha que define o valor de  d  é trocada por
        d = (double) rand () / (RAND_MAX + 1);
    

    Quais as conseqüências?

  2. Use a função RandomInteger para simular o rolar de um dado de 6 faces.

Sementes

Qualquer gerador de números pseudoaleatórios, como rand, funciona assim:   recebe o número gerado pela chamada anterior do gerador e produz um novo número pseudoaleatório.  

O número usado como entrada da primeira execução do gerador é conhecido como semente (= seed).  Você pode especificar a semente com a função srand da bilbioteca stdlib.

// A função Randomize inicializa o gerador de números 
// (pseudo)aleatórios de modo que os resultados das
// chamadas a RandomInteger e RandomReal sejam
// imprevisíveis. Se essa função não for chamada,
// as outras funções produzirão sempre a mesma 
// seqüência de valores.

void Randomize (void)
{
    srand ((int) time (NULL));
}

Dada a semente, a seqüência de números produzida pelo gerador está completamente determinada. Se você não especificar a semente, o sistema escolhe uma semente padrão (zero, se não me engano).

 

 


URL of this site: www.ime.usp.br/~pf/algoritmos/
1998 | Last modified: Sat Aug 5 08:52:17 BRT 2006
Paulo Feofiloff
IME-USP