有没有一个函数生成一个随机int数在C?或者我必须使用第三方库?


当前回答

如果你需要安全的随机字符或整数:

正如在如何在各种编程语言中安全地生成随机数中提到的,你会想要做以下事情之一:

使用libsodium的randombytes API 重新实现你自己需要的libsodium的sysrandom实现,非常小心 更广泛地说,使用/dev/urandom,而不是/dev/random。而不是OpenSSL(或其他用户空间prng)。

例如:

#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()是加密安全且无偏倚的。

其他回答

在现代的x86_64 cpu上,您可以通过_rdrand64_step()使用硬件随机数生成器。

示例代码:

#include <immintrin.h>

uint64_t randVal;
if(!_rdrand64_step(&randVal)) {
  // Report an error here: random number generation has failed!
}
// If no error occured, randVal contains a random 64-bit number

对于c, STL不存在,你必须调用rand,或者更好的是,随机。它们在标准库头文件stdlib.h中声明。rand是POSIX, random是BSD规范函数。

rand和random之间的区别是random返回一个更有用的32位随机数,而rand通常返回一个16位数。BSD手册显示rand的较低位是循环的和可预测的,因此rand对于较小的数字可能是无用的。

对于Linux C应用程序:

这是我根据上面的答案重新编写的代码,它遵循我的C代码实践并返回任意大小的随机缓冲区(具有适当的返回代码等)。确保在程序开始时调用urandom_open()一次。

int gUrandomFd = -1;

int urandom_open(void)
{
    if (gUrandomFd == -1) {
        gUrandomFd = open("/dev/urandom", O_RDONLY);
    }

    if (gUrandomFd == -1) {
        fprintf(stderr, "Error opening /dev/urandom: errno [%d], strerrer [%s]\n",
                  errno, strerror(errno));
        return -1;
    } else {
        return 0;
    }
}


void urandom_close(void)
{
    close(gUrandomFd);
    gUrandomFd = -1;
}


//
// This link essentially validates the merits of /dev/urandom:
// http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/
//
int getRandomBuffer(uint8_t *buf, int size)
{
    int ret = 0; // Return value

    if (gUrandomFd == -1) {
        fprintf(stderr, "Urandom (/dev/urandom) file not open\n");
        return -1;
    }

    ret = read(gUrandomFd, buf, size);

    if (ret != size) {
        fprintf(stderr, "Only read [%d] bytes, expected [%d]\n",
                 ret, size);
        return -1;
    } else {
        return 0;
    }
}
#include<stdio.h>
#include<stdlib.h>
#include<time.h>

//generate number in range [min,max)
int random(int min, int max){
    int number = min + rand() % (max - min);
    return number; 
}

//Driver code
int main(){
    srand(time(NULL));
    for(int i = 1; i <= 10; i++){
        printf("%d\t", random(10, 100));
    }
    return 0;
}

有人很好地解释了为什么使用rand()在给定范围内生成均匀分布的随机数是一个坏主意,我决定看看输出到底有多倾斜。我的测试案例是公平掷骰子。下面是C代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(int argc, char *argv[])
{
    int i;
    int dice[6];

    for (i = 0; i < 6; i++) 
      dice[i] = 0;
    srand(time(NULL));

    const int TOTAL = 10000000;
    for (i = 0; i < TOTAL; i++)
      dice[(rand() % 6)] += 1;

    double pers = 0.0, tpers = 0.0;
    for (i = 0; i < 6; i++) {
      pers = (dice[i] * 100.0) / TOTAL;
      printf("\t%1d  %5.2f%%\n", dice[i], pers);
      tpers += pers;
    }
    printf("\ttotal:  %6.2f%%\n", tpers);
}

这是它的输出:

 $ gcc -o t3 t3.c
 $ ./t3 
        1666598  16.67%     
        1668630  16.69%
        1667682  16.68%
        1666049  16.66%
        1665948  16.66%
        1665093  16.65%
        total:  100.00%
 $ ./t3     
        1667634  16.68%
        1665914  16.66%
        1665542  16.66%
        1667828  16.68%
        1663649  16.64%
        1669433  16.69%
        total:  100.00%

我不知道你需要你的随机数有多统一,但上面的看起来足够统一,满足大多数需求。

编辑:用比time(NULL)更好的东西初始化PRNG是个好主意。