Thread: About the function rand()

  1. #1
    Registered User
    Join Date
    Mar 2015
    Location
    BE
    Posts
    66

    About the function rand()

    Hello,

    Can you please help me understand the working of <stdlib.h> rand() function ?

    Why does the function return the same (first) number(s) again and again ? I will later use the other srand(time) function, but I'd first like to understand how rand() works. I know the int value returned by the function is different from one platform to another, but it's a huge difference (64 and 32bit windows and Linux): 16bits difference as you see:

    Code:
    int main (void) {
    
    
        printf("%d (Max) %d\n\n", rand(), RAND_MAX);
    
    
        int i;
        for (i = 0; i < 10; i++) {
            printf("%d\n", rand());
        }
    
    
        return 0;
    }

    Windows Linux
    41 (Max) 32767 1804289383 (Max) 2147483647
    18467
    6334
    26500
    19169
    15724
    11478
    29358
    26962
    24464
    5705
    846930886
    1681692777
    1714636915
    1957747793
    424238335
    719885386
    1649760492
    596516649
    1189641421
    1025202362

  2. #2
    Registered User
    Join Date
    Apr 2007
    Posts
    141
    Well the first thing you need to know, is that rand() is not random. It's deterministic. It only superficially behaves like a random number, hopefully having good correlation properties among it's bits. A lot of rand() implementations are atrocious by the way having correlations among bits and producing random numbers that all lie on the same subplane. rand() will internally update a hidden state so it's not even a real function.

    If you don't initialize the seed it will do so for you, always with the same seed. Be thankful that it does this, because otherwise you would not have reproducible code, if for example you found a bug that was exercised by just the right randomly generated input. You can make it more random by initializing the seed, perhaps by UTC time or some time varying input.

    There are some very high performance random number generators that can be very efficiently computed. Don't count on your library vendor for implementing them. Build your own Mersenne twister and your own seed tables with high performance code that you can easily copy from reputable internet sources.

    Pseudorandom number generator - Wikipedia, the free encyclopedia

  3. #3
    Registered User
    Join Date
    Mar 2015
    Location
    BE
    Posts
    66
    Yes, thank you.

    I now know from experience with my program the rand() is pseudorandom, and I got the feeling it's kind of predictable.

    If it is the case, then I can simulate that using my own function:

    Code:
    int myrandom (void);
    int my_rand_number;
    
    int main (void) {
       myrandom();
       printf("%d\n", my_rand_number);
    }    
    
    int myrandom (void) {
       my_rand_number++;
       if (my_rand_number == 100) {  //100 myrand max
          my_rand_number = 1;
       }
       return my_rand_number;
    }
    The rand() does not only return the same first value again and again, but also the result of a loop don't change, and it is not really fair:


    Windows Linux
    1 rolled 177 times.
    2 rolled 147 times.
    3 rolled 158 times.
    4 rolled 183 times.
    5 rolled 177 times.
    6 rolled 159 times.
    1 rolled 153 times.
    2 rolled 177 times.
    3 rolled 149 times.
    4 rolled 183 times.
    5 rolled 178 times.
    6 rolled 161 times.


    Code:
    int main (void) {    
    
        int my_dice_row[7] = {0,0,0,0,0,0,0};
    
    
        int i;
        for(i = 0; i <= 1000; i++){
          int tmp = (int) (rand() * 6.0 / (RAND_MAX + 1.0)) + 1;
          switch (tmp){
            case 1: my_dice_row[1]++; break;
            case 2: my_dice_row[2]++; break;
            case 3: my_dice_row[3]++; break;
            case 4: my_dice_row[4]++; break;
            case 5: my_dice_row[5]++; break;
            case 6: my_dice_row[6]++; break;
          }
        }
    
    
        for(i = 1; i <= 6; i++){
          printf ("%d rolled %d times.\n", i, my_dice_row[i]);
        }
    }

  4. #4
    TEIAM - problem solved
    Join Date
    Apr 2012
    Location
    Melbourne Australia
    Posts
    1,907
    Use
    Code:
    #include <time.h>  
    ..
    srand(time(NULL));
    To find a random enough starting point.

    FAQ > Generate random numbers? - Cprogramming.com
    Fact - Beethoven wrote his first symphony in C

  5. #5
    Registered User
    Join Date
    Jun 2011
    Posts
    4,513
    Quote Originally Posted by Carnotter View Post
    Code:
    int main (void) {    
    
        int my_dice_row[7] = {0,0,0,0,0,0,0};
    
    
        int i;
        for(i = 0; i <= 1000; i++){
          int tmp = (int) (rand() * 6.0 / (RAND_MAX + 1.0)) + 1;
          switch (tmp){
            case 1: my_dice_row[1]++; break;
            case 2: my_dice_row[2]++; break;
            case 3: my_dice_row[3]++; break;
            case 4: my_dice_row[4]++; break;
            case 5: my_dice_row[5]++; break;
            case 6: my_dice_row[6]++; break;
          }
        }
    
    
        for(i = 1; i <= 6; i++){
          printf ("%d rolled %d times.\n", i, my_dice_row[i]);
        }
    }
    If you really wanted to be clever, you could replace your entire "switch()" with a single line:

    Code:
    my_dice_row[tmp]++;

  6. #6
    Registered User
    Join Date
    Mar 2015
    Location
    BE
    Posts
    66
    Quote Originally Posted by Click_here View Post
    Use
    Code:
    #include <time.h>  
    ..
    srand(time(NULL));
    To find a random enough starting point.

    FAQ > Generate random numbers? - Cprogramming.com
    Yes, I mentioned that. There are some things I do not understand in srand(). But first I am trying to explain myself the working of rand(). After I understand its working and limitations, I will use srand(). The best solution at the end is what SevenThunders suggested: create your own.

    Please, keep watching my thread. I will post later something related to srand(time(NULL)).

  7. #7
    Registered User
    Join Date
    Mar 2015
    Location
    BE
    Posts
    66
    Quote Originally Posted by Matticus View Post
    If you really wanted to be clever, you could replace your entire "switch()" with a single line:

    Code:
    my_dice_row[tmp]++;
    I know that.
    But it's a manner: try always to use the most recent C's aspect you've learned. We first did nested if's, after that switch and there I use it.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Carnotter
    There are some things I do not understand in srand(). But first I am trying to explain myself the working of rand().
    You cannot really divorce the understanding of the two because they very much go together.

    Quote Originally Posted by Carnotter
    The best solution at the end is what SevenThunders suggested: create your own.
    That would be a bad idea as, not having expertise in this, you could well come up with a solution that is worse than your standard library implementation's existing srand()/rand(). Thankfully, that was not what SevenThunders suggested. Rather, SevenThunders suggested copying the implementation of a known PRNG from an online source.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Mar 2015
    Location
    BE
    Posts
    66
    Quote Originally Posted by laserlight View Post
    You cannot really divorce the understanding of the two because they very much go together.


    That would be a bad idea as, not having expertise in this, you could well come up with a solution that is worse than your standard library implementation's existing srand()/rand(). Thankfully, that was not what SevenThunders suggested. Rather, SevenThunders suggested copying the implementation of a known PRNG from an online source.
    I can not or may not copy anything I don't understand.

    There are some bizarre things happening while I was using the srand();

    It's OK to use it just once, but what will happen if I call it into a for loop?

    Code:
    // srand() call here: OK
    for (i=0;i<10;i++) {        
       srand(time(NULL)); // here not OK
       int tmp = rand();
       printf("%d\n", tmp);
    }
    I get the same values. It's better than rand() because it generates another number each time I execute the program.

    The second problem is that it doesn't really work when I manipulate the rand() function to get a range I want.

    Code:
    int main(void){	
    	srand(time(NULL));
    	
    	int tmp = (int) (rand() * 6.0 / (RAND_MAX +1.0)) + 1;
    	int i=0;
    	do {
    		printf("%d\n", tmp);
    		i++;
    	} while (i<10);	
    	
    	return 0;		
    }

  10. #10
    Registered User
    Join Date
    Apr 2007
    Posts
    141
    Well let me help you with some fiendishly clever random number generators, from some obsessed hardware hackers with good performance.

    Code:
    #include <stdint.h>
     
    /* These state variables must be initialized so that they are not all zero. */
    uint32_t x, y, z, w;
     
    uint32_t xorshift128(void) {
        uint32_t t = x ^ (x << 11);
        x = y; y = z; z = w;
        return w = w ^ (w >> 19) ^ t ^ (t >> 8);
    }
    Even better 64 bit generators can be found here:
    Xorshift - Wikipedia, the free encyclopedia

    Note the amount of state that must be carried. Thus it is not reentrant. If you want fast parallel random number generators (ie a lot of numbers at once), that's a whole new ballgame.

  11. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,663
    > The second problem is that it doesn't really work when I manipulate the rand() function to get a range I want.
    No, the second problem is your rand() call ISN'T inside the loop.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Carnotter
    I can not or may not copy anything I don't understand.
    You have a choice: is your immediate intention to learn about PRNGs and implement them, or is it to use a PRNG to accomplish some other task? If it is a former, then by all means read the literature, investigate existing PRNGs, experiment with your own PRNGs, etc. If it is the latter, then you just need to know what are PRNGs, what they do and how to use them, and then have some idea as to the appropriate usage of the PRNG that you select, and you're good to go even if you don't quite understand the details. Even if you have already done the former, you might still choose to use someone else's well known PRNG, if you find that your own best effort is not actually better for the purpose that you have in mind.

    Quote Originally Posted by Carnotter
    There are some bizarre things happening while I was using the srand();

    It's OK to use it just once, but what will happen if I call it into a for loop?
    The rule of thumb is to call srand exactly once in your program, typically near the start of the main function. If you call it in a loop using the current time as the seed, then if your loop runs several times within the granularity of the time function, you end up seeding with the same seed prior to each call to rand(), thus your call to rand() will result in the same value over and over again. If your loop runs slowly or the granularity of time is small enough, you end up seeding with different seeds, but then you might as well dispense with srand and rand and just hash the bytes of the return value of time, or something like that.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Registered User
    Join Date
    Mar 2015
    Location
    BE
    Posts
    66
    SevenThunders ,
    Thanks but that belongs to another higher branch of programming with bits, I think. At the moment, I am trying to understand and use standard srand() rand(). And we didn't handle those data types yet.

    Salem,
    I really don't know why I didn't see that!
    Indeed, not inside the loop. Thanks.


    laserlight,
    I tested that using <windows.h> Sleep() function.


    Code:
    int main(void) {
        int i;
        for (i = 0; i < 10; i++) {
            srand(time(NULL));
            int tmp = rand();
            printf("%d\n", tmp);
            Sleep(1000); //this function doesn't smell C. It starts with capital S!
        }
    
    
        return 0;
    }
    
    


    It's printing now different values, but in kind of sequence order. So, I should use it just once at the beginning of a block where I use it. Thanks.


    Last edited by Carnotter; 04-02-2015 at 09:18 AM.

  14. #14
    Registered User
    Join Date
    Mar 2015
    Location
    BE
    Posts
    66
    My program at this moment. I'm busy with bringing some improvements into it (using thread development process), but please comment, criticize and make suggestions.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    
    
    int main (void) {
        srand(time(NULL));
    
    
        // get players
        
        int nplayers;
    
    
        printf("How many players? ");
    
    
        while (scanf("%d", &nplayers) != 1) {
            int c;
            while ((c = getchar()) != '\n' && c != EOF);
            printf("Enter a valid number: ");
        }
    
    
        putchar('\n');
    
    
        if (nplayers <= 0) {
            printf("No playing today ..");
            return 0;
        }
    
    
        // get ID's of players
        
        int players[nplayers][2];
        int i;
        for (i = 0; i < nplayers; i++) {
            printf("Player %d ID: ", i+1);
    
    
            while (scanf("%d", &players[i][0]) != 1) {
                int c;
                while ((c = getchar()) != '\n' && c != EOF);
                printf("Enter a valid number: ");
            }
        }
    
    
        putchar('\n');
    
    
    
    
    
    
        // let's play
        
        for (i = 0; i < nplayers; i++) {
    
    
            int tmp_rand = (int) (rand() * 100.0 / (RAND_MAX + 1.0)) + 1;
    
    
            int attempts = 0;
    
    
            printf("---[Player %d]---\nGuess the number between 1 and 100 :\n",
                   players[i][0]);
    
    
            while (1) {
                int shot;
    
    
                while (scanf("%d",&shot) != 1) {
                    int c;
                    while ((c = getchar()) != '\n' && c != EOF);
                    printf("Enter a valid number: ");
                }
    
    
                ++attempts;
    
    
                if (shot == tmp_rand) {
                    printf("Good job, player %d! You guessed the number"
                           "in %d guesses!\n\n", players[i][0], attempts);
                    players[i][1] = attempts;
                    break;
                } else if (shot < tmp_rand) {
                    puts("Hint: too low!");
                } else {
                    puts("Hint: too high!");
                }
            }
        }
    
    
        // print the results
        
        printf("Player ID \t Score\n----------------------\n");
        
        for (i = 0; i < nplayers; i++) {
          printf("%9d \t %d\n", players[i][0], players[i][1]);
        }
    
    
        return 0;
    }
    Last edited by Carnotter; 04-02-2015 at 04:29 PM. Reason: add stats (printing players and their scores)

  15. #15
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Code:
        while (scanf("%d", &nplayers) != 1) {
            int c;
            while ((c = getchar()) != '\n' && c != EOF);
            printf("Enter a valid number: ");
        }
     
     
        putchar('\n');
     
     
        if (nplayers <= 0) {
            printf("No playing today ..");
            return 0;
        }
    Not sure if it is required to be this way but are you sure you want to quit the whole program just because there are <= 0 players? To me that seems like a user error. You should force the input to be 1 or more, expecially since nplayers is going to be the size of a variable length array.

    Also the attempts variable will eventually overflow. Look at limits.h. Granted, that is almost certainly going to be a very big number, but an int is not infinitely big. It is a range, and when a signed integer overflows, the behavior of the program is undefined. You should fix the game by imposing a limited number of attempts.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 11-14-2011, 08:08 AM
  2. Is there any function better than rand()
    By ubern00ber in forum C++ Programming
    Replies: 21
    Last Post: 03-09-2006, 08:53 PM
  3. Rand() function...
    By Ash1981 in forum C Programming
    Replies: 7
    Last Post: 01-26-2006, 09:04 AM
  4. rand() function?
    By s_ny33 in forum C++ Programming
    Replies: 2
    Last Post: 03-08-2005, 07:58 PM
  5. Rand() function
    By Da-Nuka in forum C++ Programming
    Replies: 10
    Last Post: 12-26-2004, 08:12 AM