1. Este site usa cookies. Ao continuar a usar este site está a concordar com o nosso uso de cookies. Saber Mais.

Trabalhar com numeros aleatórios em c++

Discussão em 'Programação' iniciada por Ronnie_03, 2 de Setembro de 2008. (Respostas: 19; Visualizações: 13180)

  1. Ronnie_03

    Ronnie_03 Power Member

    Boas,

    Precisava que alguém me explicasse como é que se faz com que o computador gere um numero aleatório num dado intervalo, porque no tutorial que estou a seguir dão um exemplo mas não explicam muito bem o exemplo.

    O exemplo é este:

    Código:
    #include <iostream>
    #include <stdlib.h>     //para poderem usar o rand()
    #include <windows.h>    //para poderem usar o GetTickCount()
    using namespace std;
    /***********************************************************
                int getRandom(int de, int ate)
    DESC: gera números aleatórios que vão desde "de" até "ate"
    ***********************************************************/
    int getRandom(int de, int ate);
    int main()
    {
        srand( GetTickCount() );    //explicarei isto quando falar de arrays.
                                    //experimentem retirar e correr o programa varias vezes!
        for (int x = 0; x < 10; x++)
            cout << getRandom(0,5) << endl;     //não é necessário { } porque é so uma linha
    
        cin.get();
        return 0;
    }
    int getRandom(int de, int ate)
    {
        int random;
        ate -= de;
        random = rand() % (ate + 1) + de;
        return random;
    }
    
    Gostava que alguém me explicasse como é que este exemplo funciona.

    Cumps
     
  2. Aparicio

    Aparicio /dev/mod
    Staff Member

    http://www.cplusplus.com/reference/clibrary/cstdlib/rand.html

    Antes de usares a função rand deves usar a função srand() para que a sequência dos números varie de acordo com a semente ( o argumento da função srand ).
    Cada semente vai provocar uma sequência diferente, daí se utilizarem funções que variem ao longo do tempo para obter essa semente, utiliza-se por exemplo o time(NULL) ou nesse caso do GetTickCount(), "Retrieves the number of milliseconds that have elapsed since the system was started".

    Depois o rand() retorna um valor normalmente entre 0 e 32767.
    Para que os valores sejam no intervalo que queiras utiliza-se a operação modulo ( resto da divisão ).

    Por exemplo para valores entre 0 e 3 ( 4 valores ):

    Código:
    rand() = 1000;  1000 % 4 = 0 ( 1000 / 4 = 255 );
    rand() = 1001;  1001 % 4 = 1 ( 1001 / 2 = 250,25 );
    rand() = 1002;  1002 % 4 = 2 ( 1001 / 2 = 250,5 );
    rand() = 1003;  1003 % 4 = 3 ( 1001 / 2 = 250,75 );
    rand() = 1004;  1004 % 4 = 0 ( 1004 / 2 = 251 );
    ...
    Se quiseres a partir de n, somas n ao resultado.

    Para valores entre 11 e 20 inclusive:

    Para saber quantos números são faz-se a diferença e soma-se 1.
    20 - 11 = 9, mas não são 9 números, são 10.

    Código:
    rand() % 10 vai dar valores entre 0 e 9, e como se quer entre 11 e soma-se 11.
    rand() % 10 + 11 = 11, 12, ... 20.
    PS: Na verdade isto são números pseudo-aleatórios.
     
    Última edição: 4 de Setembro de 2008
  3. Ronnie_03

    Ronnie_03 Power Member

    Antes de mais obrigado, Aparicio, pela tua explicação...consegui perceber quase tudo, mas
    agora que estava a pensar fazer um programa que gerasse números aleatórios, tive a ver o exemplo que estava no meu post anterior:

    Código:
    #include <iostream>
    #include <stdlib.h>     //para poderem usar o rand()
    #include <windows.h>    //para poderem usar o GetTickCount()
    using namespace std;
    int getRandom(int de, int ate);
    int main()
    {
        [COLOR=red]srand[/COLOR]( GetTickCount() );    //explicarei isto quando falar de arrays.
                                    //experimentem retirar e correr o programa varias vezes!
        for (int x = 0; x < 10; x++)
            cout << getRandom(0,5) << endl;     //não é necessário { } porque é so uma linha
     
        cin.get();
        return 0;
    }
    int getRandom(int de, int ate)
    {
        int random;
        ate -= de;
        random = [COLOR=red]rand()[/COLOR] % (ate + 1) + de;
        return random;
    }
    
    E gostava que me explicassem o quê que está a fazer o srand (GetTickCount() ), uma vez que o valor que vai devolvendo não está a ser guardado.
    Eu assinalei a vermelho o rand(), mas percebi o quê que ele está a fazer, só queria era saber se ele está associado ao srand().

    P.S. Eu sei o quê que faz o srand(), devolve um numero aleatório conforme o argumento, sendo por isso que o argumento é o GetTickCount, ou seja, é um argumento que está sempre a variar no tempo.
     
  4. Aparicio

    Aparicio /dev/mod
    Staff Member

    O srand() não retorna um número aleatório, isso faz o rand();
    O que o srand() faz é o chamado random seed, ou seja que faz com que a sequência dos números devolvidos pelo rand() varie conforme o argumento varie de execução para execução.
     
  5. Demio

    Demio Power Member

  6. Ronnie_03

    Ronnie_03 Power Member

    Tenho só mais uma dúvida nesta função:

    Código:
     
    int getRandom(int de, int ate)
    {
        int random;
    [COLOR=red]   ate -= de;[/COLOR]
        random = rand() % (ate + 1) [COLOR=red]+ de[/COLOR];
        return random;
    }
    
    Já experimentei com as duas funções e o programa funciona correctamente, mas queria saber se aquela função é equivalente a esta:

    Código:
     
    int getRandom(int de, int ate)
    {
        int random;
        ate -= de;
        random = rand() % (ate + 1) + de;
        return random;
    }
    
    O que está a vermelho na função anterior foi o que eu apaguei.
     
  7. Aparicio

    Aparicio /dev/mod
    Staff Member

    Tens a certeza que funciona?
    Sem essas partes a vermelho experimenta gerar números de 10 a 12 e vês que dá números de 0 a 11.
     
  8. Ronnie_03

    Ronnie_03 Power Member

    Tens toda a razão, mas então não percebo estas duas linhas:

    Código:
     
    ate -= de;
    random = rand() % (ate + 1) + de;
    
    Fico com a ideia que rand()% (ate +1) gera numeros aleatórios de 0 até ao ate + 1, sendo depois adicionado o de, para os numeros em vez de começarem no zero começar no de, certo??


    EDIT: Muito obrigado pela explicação Aparicio, finalmente percebi tudo isto.
    Já agora também percebi porquê que no meu exemplo também funcionava como eu disse...foi porque queriamos numeros aleatórios a partir do zero.
     
    Última edição: 4 de Setembro de 2008
  9. Aparicio

    Aparicio /dev/mod
    Staff Member

    Sim, basicamente é isso.

    Código:
    n = ate - de + 1;
    random = rand() % n + de;
    
    É equivalente mas é para simplificar.

    rand() % n gera n números diferentes, de 0 até n - 1.
    Como é que obtens quantos números queres?
    Tens o limite máximo ate, ao qual se subtraíres o limite mínimo de dá-te a quantidade de números menos um.

    Se quiseres números por exemplo de 10 a 20.

    Para saberes quantos números tens de gerar fazes ate - de + 1 ou seja 20 - 10 + 1 = 11.
    10, 11, 12, 13, 14, 15, 16, 17, 18, 19 20. 11 números.

    Portanto rand() % 11 vai dar-te 11 os números diferentes de 0 a 10.
    Como querias de 10 a 20 adicionas 10.
     
  10. Demio

    Demio Power Member

    De salientar que o meu método funciona tanto com "int"s como com "double"s. O vosso com o "modulus" só funciona com "int"s ;)
     
  11. Aparicio

    Aparicio /dev/mod
    Staff Member

    Na verdade até existe uma função no math.h para calcular o modulo de double's. :p

    Código:
    double random( double de, double ate )
        {
        return [B]fmod([/B] rand(), (ate - de + 1) [B])[/B] + de;
        }
    Mas o teu método continua a ser uma boa alternativa.
     
  12. Demio

    Demio Power Member

    Já usei o fmod em algumas coisas, em certos comportamentos não é exactamente igual ao operador "%". Mas já não me lembro exactamente onde tive problemas. Sei que tive de fazer uns hacks para aquilo funcionar como esperado (as coisas em que usei o fmod).

    Edit: yep, tive de fazer um "realMod" manualmente porque o fmod não funcionava bem para valores negativos.

    O resultado foi este:

    Código:
    	double PhysicsEngine::realMod(double x, double y) {
    		return x - y * floor(x / y);
    	}
    
    from http://code.google.com/p/roids/sour...dependent/sources/asteroids/PhysicsEngine.cpp
     
    Última edição: 5 de Setembro de 2008
  13. Olha nao é por nada nao mas deveria ser colocado a adição do 1 depois de calcular com o rand.

    Código:
    random = rand() % (ate + 1) + de;
    Código:
    return fmod( rand(), (ate - de + 1) ) + de;
    todos os dois começao de 0 ate o numero, ou seja ali vai dar um numero por exemplo de 10 a 20 vai sair de 11 a 19, pq o rand ta de (ate - de +1) e deve ficar rand % (ate - de)+1+de

    se rand % (10) te da um numero de 0 a 9, oq te faz pensar q rand % (9+1) vai te dar numeros de 1 a 10?
    ahh sim claro, no de voces ficaria algo do tipo rand %(10+1) e isso é igual a rand % (11) q gera de 0 a 10, bom sim gera o 10, mas gera o 0.
     
    Última edição: 13 de Setembro de 2008
  14. Ronnie_03

    Ronnie_03 Power Member

    Não percebi o teu objectivo com este post, mas
    Código:
    rand %(10)
    de facto gera numeros entre 0 e 9 e se quisesse entre 1 e 10 não é
    Código:
    rand %(9+1)
    mas antes
    Código:
    rand % (10) + 1
     
    Última edição: 13 de Setembro de 2008
  15. hehhe acho q me empolguei e nao devo ter percebido q a intençao era de gerar um numero de (10,20) gerar 10,11....20 e nao de 11,12...20.

    bom pelo q vi oq aparicio coloco seria como eu disse mesmo, mas de qualquer forma isso fico bem esclarecido.

    Agora vamos pro meu problema, kra nao consigo usar isso com alegro, o meu problema ta no conflito do allegro com window.h, diz q ja tem um typdef bitmap, e nao sei de outro jeito melhor de gerar seed q nao seja pelo GetTickCounts. Acho q ele da um numero aleatorio mais convincente ;)

    Espero q alguem ai saiba usar bem o allegro, mas se nao for e souber de uma boa soluçao pra uma seed legal agradeço!!
     
  16. Ronnie, acho q vc me entendeu mal ou eu q me expliquei mal, eu nao falei uma afirmativa de q rand(9+1) vai dar entre 1 e 10, apenas deixei a pergunta no ar...
    deixa pra la, foi erro meu.
     
  17. Ronnie_03

    Ronnie_03 Power Member

    Se calhar fui mesmo eu que não percebi a tua pergunta, mas de qualquer forma já percebi o que querias dizer!!

    Quanto á tua dúvida do post anterior não te sei responder, mas espera pela resposta de outro user, já que há aqui muito pessoal que percebe mesmo de programação.
     
  18. obrigado pela força ai ronnie!!
     
  19. Aparicio

    Aparicio /dev/mod
    Staff Member

    Pelo que percebi queres usar o GetTickCounts para gerar o seed mas precisas do windows.h que entra em conflito com a biblioteca do allegro.
    Não podes usar o time(NULL) para gerar o seed?
     
  20. So passando aki pra dizer q ja achei oque queria e deixo aki o descobri.

    Allegro oferece um header file chamado winalleg.h, com ele vc pode usar os recursos do windows.h sem conflitos com o allegro.h

    Allegro fez isso justamente por causa dos conflitos entao acho q da pra fazer de tudo q fazia antes com o windows.h nao tenho certeza apenas testei aki e pelos programas de exemplos q vem junto com allegro posso ver q funçoes de janelas e menus funcionam e o GetTickCount funcionou tb.

    Mas ai se tem alguma outra forma melhor q usar o GetTickCount por favor postem ai.

    Ah sim no visual c++ pra fazer um contador do GetTickCount usava um gcnew, gostaria de saber se no dev-c++ usando o allegro se usa do mesmo jeito, se nao, por favor me diz qual.


    vlw!!
     

Partilhar esta Página