How to generate a random int in C?

后端 未结 27 2082
故里飘歌
故里飘歌 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:35

    Lets go through this. First we use the srand() function to seed the randomizer. Basically, the computer can generate random numbers based on the number that is fed to srand(). If you gave the same seed value, then the same random numbers would be generated every time.

    Therefore, we have to seed the randomizer with a value that is always changing. We do this by feeding it the value of the current time with the time() function.

    Now, when we call rand(), a new random number will be produced every time.

        #include <stdio.h>
    
        int random_number(int min_num, int max_num);
    
        int main(void)
        {
            printf("Min : 1 Max : 40 %d\n", random_number(1,40));
            printf("Min : 100 Max : 1000 %d\n",random_number(100,1000));
            return 0;
        }
    
        int random_number(int min_num, int max_num)
        {
            int result = 0, low_num = 0, hi_num = 0;
    
            if (min_num < max_num)
            {
                low_num = min_num;
                hi_num = max_num + 1; // include max_num in output
            } else {
                low_num = max_num + 1; // include max_num in output
                hi_num = min_num;
            }
    
            srand(time(NULL));
            result = (rand() % (hi_num - low_num)) + low_num;
            return result;
        }
    
    0 讨论(0)
  • 2020-11-22 00:36

    Note: Don't use rand() for security. If you need a cryptographically secure number, see this answer instead.

    #include <time.h>
    #include <stdlib.h>
    
    srand(time(NULL));   // Initialization, should only be called once.
    int r = rand();      // Returns a pseudo-random integer between 0 and RAND_MAX.
    

    Edit: On Linux, you might prefer to use random and srandom.

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

    rand() is the most convenient way to generate random numbers.

    You may also catch random number from any online service like random.org.

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

    If you need secure random characters or integers:

    As addressed in how to safely generate random numbers in various programming languages, you'll want to do one of the following:

    • Use libsodium's randombytes API
    • Re-implement what you need from libsodium's sysrandom implementation yourself, very carefully
    • More broadly, use /dev/urandom, not /dev/random. Not OpenSSL (or other userspace PRNGs).

    For example:

    #include "sodium.h"
    
    int foo()
    {
        char myString[32];
        uint32_t myInt;
    
        if (sodium_init() < 0) {
            /* panic! the library couldn't be initialized, it is not safe to use */
            return 1; 
        }
    
    
        /* myString will be an array of 32 random bytes, not null-terminated */        
        randombytes_buf(myString, 32);
    
        /* myInt will be a random number between 0 and 9 */
        myInt = randombytes_uniform(10);
    }
    

    randombytes_uniform() is cryptographically secure and unbiased.

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

    Have a look at ISAAC (Indirection, Shift, Accumulate, Add, and Count). Its uniformly distributed and has an average cycle length of 2^8295.

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

    If your system supports the arc4random family of functions I would recommend using those instead the standard rand function.

    The arc4random family includes:

    uint32_t arc4random(void)
    void arc4random_buf(void *buf, size_t bytes)
    uint32_t arc4random_uniform(uint32_t limit)
    void arc4random_stir(void)
    void arc4random_addrandom(unsigned char *dat, int datlen)
    

    arc4random returns a random 32-bit unsigned integer.

    arc4random_buf puts random content in it's parameter buf : void *. The amount of content is determined by the bytes : size_t parameter.

    arc4random_uniform returns a random 32-bit unsigned integer which follows the rule: 0 <= arc4random_uniform(limit) < limit, where limit is also an unsigned 32-bit integer.

    arc4random_stir reads data from /dev/urandom and passes the data to arc4random_addrandom to additionally randomize it's internal random number pool.

    arc4random_addrandom is used by arc4random_stir to populate it's internal random number pool according to the data passed to it.

    If you do not have these functions, but you are on Unix, then you can use this code:

    /* This is C, not C++ */
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <unistd.h>
    #include <stdlib.h> /* exit */
    #include <stdio.h> /* printf */
    
    int urandom_fd = -2;
    
    void urandom_init() {
      urandom_fd = open("/dev/urandom", O_RDONLY);
    
      if (urandom_fd == -1) {
        int errsv = urandom_fd;
        printf("Error opening [/dev/urandom]: %i\n", errsv);
        exit(1);
      }
    }
    
    unsigned long urandom() {
      unsigned long buf_impl;
      unsigned long *buf = &buf_impl;
    
      if (urandom_fd == -2) {
        urandom_init();
      }
    
      /* Read sizeof(long) bytes (usually 8) into *buf, which points to buf_impl */
      read(urandom_fd, buf, sizeof(long));
      return buf_impl;
    }
    

    The urandom_init function opens the /dev/urandom device, and puts the file descriptor in urandom_fd.

    The urandom function is basically the same as a call to rand, except more secure, and it returns a long (easily changeable).

    However, /dev/urandom can be a little slow, so it is recommended that you use it as a seed for a different random number generator.

    If your system does not have a /dev/urandom, but does have a /dev/random or similar file, then you can simply change the path passed to open in urandom_init. The calls and APIs used in urandom_init and urandom are (I believe) POSIX-compliant, and as such, should work on most, if not all POSIX compliant systems.

    Notes: A read from /dev/urandom will NOT block if there is insufficient entropy available, so values generated under such circumstances may be cryptographically insecure. If you are worried about that, then use /dev/random, which will always block if there is insufficient entropy.

    If you are on another system(i.e. Windows), then use rand or some internal Windows specific platform-dependent non-portable API.

    Wrapper function for urandom, rand, or arc4random calls:

    #define RAND_IMPL /* urandom(see large code block) | rand | arc4random */
    
    int myRandom(int bottom, int top){
        return (RAND_IMPL() % (top - bottom)) + bottom;
    }
    
    0 讨论(0)
提交回复
热议问题