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


当前回答

#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;
}

其他回答

我的极简解决方案应该适用于范围内的随机数[min, max)。在调用函数之前使用srand(time(NULL))。

int range_rand(int min_num, int max_num) {
    if (min_num >= max_num) {
        fprintf(stderr, "min_num is greater or equal than max_num!\n"); 
    }
    return min_num + (rand() % (max_num - min_num));
} 

你也可以使用mathgl库#include <mgl2/mgl_cf.h>(虽然首先你需要安装它,我自己通过MSYS2安装)函数mgl_rnd()。它也有均匀分布,高斯分布等等。这是ez的用法。但我不知道它的特点。

STL是c++,不是C,所以我不知道你想要什么。然而,如果你想使用C语言,则有rand()和srand()函数:

int rand(void);

void srand(unsigned seed);

它们都是ANSI c的一部分。还有random()函数:

long random(void);

但据我所知,random()不是标准的ANSI c。第三方库可能不是一个坏主意,但这完全取决于您真正需要生成的数字的随机程度。

标准的C函数是rand()。它可以用来发纸牌,但很糟糕。rand()的许多实现通过一个简短的数字列表循环,低位的周期更短。一些程序调用rand()的方式很糟糕,计算一个传递给srand()的好种子也很困难。

在C语言中生成随机数的最佳方法是使用第三方库,如OpenSSL。例如,

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/rand.h>

/* Random integer in [0, limit) */
unsigned int random_uint(unsigned int limit) {
    union {
        unsigned int i;
        unsigned char c[sizeof(unsigned int)];
    } u;

    do {
        if (!RAND_bytes(u.c, sizeof(u.c))) {
            fprintf(stderr, "Can't get random bytes!\n");
            exit(1);
        }
    } while (u.i < (-limit % limit)); /* u.i < (2**size % limit) */
    return u.i % limit;
}

/* Random double in [0.0, 1.0) */
double random_double() {
    union {
        uint64_t i;
        unsigned char c[sizeof(uint64_t)];
    } u;

    if (!RAND_bytes(u.c, sizeof(u.c))) {
        fprintf(stderr, "Can't get random bytes!\n");
        exit(1);
    }
    /* 53 bits / 2**53 */
    return (u.i >> 11) * (1.0/9007199254740992.0);
}

int main() {
    printf("Dice: %d\n", (int)(random_uint(6) + 1));
    printf("Double: %f\n", random_double());
    return 0;
}

为什么有这么多代码?其他语言,如Java和Ruby,都有用于随机整数或浮点数的函数。OpenSSL只提供随机字节,因此我尝试模拟Java或Ruby如何将它们转换为整数或浮点数。

对于整数,我们要避免模偏置。假设我们从rand() % 10000中得到一些随机的4位整数,但是rand()只能返回0到32767(就像在Microsoft Windows中那样)。0到2767之间的每个数字出现的频率要高于2768到9999之间的每个数字。为了消除偏差,我们可以在值低于2768时重试rand(),因为从2768到32767的30000值统一映射到从0到9999的10000值。

对于浮点数,我们需要53个随机位,因为double类型拥有53位精度(假设它是IEEE double类型)。如果我们使用超过53位,就会产生舍入偏差。有些程序员写rand() / (double)RAND_MAX这样的代码,但是rand()可能只返回31位,或者在Windows中只返回15位。

OpenSSL的RAND_bytes()可能通过读取Linux中的/dev/urandom来自行播种。如果我们需要很多随机数,从/dev/urandom读取它们会很慢,因为它们必须从内核复制。允许OpenSSL从种子中生成更多的随机数会更快。

更多关于随机数的内容:

Perl的Perl_seed()是一个如何在C中为srand()计算种子的例子。如果它不能读取/dev/ urrandom,它会混合来自当前时间、进程ID和一些指针的比特。 OpenBSD的arc4random_uniform()解释了模偏置。 random的Java API描述了从随机整数中去除偏差的算法,并将53位打包到随机浮点数中。

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

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