How to generate a random int in C?

后端 未结 27 2079
故里飘歌
故里飘歌 2020-11-22 00:31

Is there a function to generate a random int number in C? Or will I have to use a third party library?

相关标签:
27条回答
  • 2020-11-22 00:32

    The rand() function in <stdlib.h> returns a pseudo-random integer between 0 and RAND_MAX. You can use srand(unsigned int seed) to set a seed.

    It's common practice to use the % operator in conjunction with rand() to get a different range (though bear in mind that this throws off the uniformity somewhat). For example:

    /* random int between 0 and 19 */
    int r = rand() % 20;
    

    If you really care about uniformity you can do something like this:

    /* Returns an integer in the range [0, n).
     *
     * Uses rand(), and so is affected-by/affects the same seed.
     */
    int randint(int n) {
      if ((n - 1) == RAND_MAX) {
        return rand();
      } else {
        // Supporting larger values for n would requires an even more
        // elaborate implementation that combines multiple calls to rand()
        assert (n <= RAND_MAX)
    
        // Chop off all of the values that would cause skew...
        int end = RAND_MAX / n; // truncate skew
        assert (end > 0);
        end *= n;
    
        // ... and ignore results from rand() that fall above that limit.
        // (Worst case the loop condition should succeed 50% of the time,
        // so we can expect to bail out of this loop pretty quickly.)
        int r;
        while ((r = rand()) >= end);
    
        return r % n;
      }
    }
    
    0 讨论(0)
  • 2020-11-22 00:33

    I had a serious issue with pseudo random number generator in my recent application: I repeatidly called my C program via a pyhton script and I was using as seed the following code:

    srand(time(NULL))
    

    However, since:

    • rand will generate the same pseudo random sequence give the same seed in srand (see man srand);
    • As already stated, time function changes only second from second: if your application is run multiple times within the same second, time will return the same value each time.

    My program generated the same sequence of numbers. You can do 3 things to solve this problem:

    1. mix time output with some other information changing on runs (in my application, the output name):

      srand(time(NULL) | getHashOfString(outputName))
      

      I used djb2 as my hash function.

    2. Increase time resolution. On my platform, clock_gettime was available, so I use it:

      #include<time.h>
      struct timespec nanos;
      clock_gettime(CLOCK_MONOTONIC, &nanos)
      srand(nanos.tv_nsec);
      
    3. Use both methods together:

      #include<time.h>
      struct timespec nanos;
      clock_gettime(CLOCK_MONOTONIC, &nanos)
      srand(nanos.tv_nsec | getHashOfString(outputName));
      

    Option 3 ensures you (as far as i know) the best seed randomity, but it may create a difference only on very fast application. In my opinion option 2 is a safe bet.

    0 讨论(0)
  • 2020-11-22 00:34

    You want to use rand(). Note (VERY IMPORTANT): make sure to set the seed for the rand function. If you do not, your random numbers are not truly random. This is very, very, very important. Thankfully, you can usually use some combination of the system ticks timer and the date to get a good seed.

    0 讨论(0)
  • 2020-11-22 00:34

    FWIW, the answer is that yes, there is a stdlib.h function called rand; this function is tuned primarily for speed and distribution, not for unpredictability. Almost all built-in random functions for various languages and frameworks use this function by default. There are also "cryptographic" random number generators that are much less predictable, but run much slower. These should be used in any sort of security-related application.

    0 讨论(0)
  • 2020-11-22 00:34

    C Program to generate random number between 9 and 50

    #include <time.h>
    #include <stdlib.h>
    
    int main()
    {
        srand(time(NULL));
        int lowerLimit = 10, upperLimit = 50;
        int r =  lowerLimit + rand() % (upperLimit - lowerLimit);
        printf("%d", r);
    }
    

    In general we can generate a random number between lowerLimit and upperLimit-1

    i.e lowerLimit is inclusive or say r ∈ [ lowerLimit, upperLimit )

    0 讨论(0)
  • 2020-11-22 00:34

    Despite all the people suggestion rand() here, you don't want to use rand() unless you have to! The random numbers that rand() produces are often very bad. To quote from the Linux man page:

    The versions of rand() and srand() in the Linux C Library use the same random number generator as random(3) and srandom(3), so the lower-order bits should be as random as the higher-order bits. However, on older rand() implementations, and on current implementations on different systems, the lower-order bits are much less random than the higher-order bits. Do not use this function in applications intended to be portable when good randomness is needed. (Use random(3) instead.)

    Regarding portability, random() is also defined by the POSIX standard for quite some time now. rand() is older, it appeared already in the first POSIX.1 spec (IEEE Std 1003.1-1988), whereas random() first appeared in POSIX.1-2001 (IEEE Std 1003.1-2001), yet the current POSIX standard is already POSIX.1-2008 (IEEE Std 1003.1-2008), which received an update just a year ago (IEEE Std 1003.1-2008, 2016 Edition). So I would consider random() to be very portable.

    POSIX.1-2001 also introduced the lrand48() and mrand48() functions, see here:

    This family of functions shall generate pseudo-random numbers using a linear congruential algorithm and 48-bit integer arithmetic.

    And pretty good pseudo random source is the arc4random() function that is available on many systems. Not part of any official standard, appeared in BSD around 1997 but you can find it on systems like Linux and macOS/iOS.

    0 讨论(0)
提交回复
热议问题