• 生成随机数的N种方式


    首先需要说明的是,计算机中生成的随机数严格来说都是伪随机,即非真正的随机数,真正随机数的随机样本不可重现。那么我们来看看代码中有哪些方式可以生成随机数。

    rand

    rand函数声明如下:

    #include <stdlib.h>
    int rand(void);
    

    rand函数返回[0,RAND_MAX)范围的随机整数,在我的机器上,RAND_MAX为2147483647。

    使用示例:

    #include<stdlib.h>
    #include<stdio.h>
    int main(void)
    {
        int i = 0;
        while(i < 5)
        {
            printf("%d ",rand());
            i++;
         }
        printf("
    ");
        return 0;
    }
    

    编译运行:

    $ gcc -o rand rand.c
    ./rand
    1804289383 846930886 1681692777 1714636915 1957747793
    

    多运行几次,你就会惊喜地发现,每次运行的结果都是一样的!!!这还玩个毛线?

    srand

    别急,rand虽然每次运行的结果都是一样的,那是因为它的种子默认为1。每一个种子会有一串看似随机的序列,每次取下一个出来,整体都近乎是随机分布的。但是如果你的种子每次都是一样的,那么每次运行可能得到的结果也是一样的。我们需要利用srand给它一个种子。

    #include <stdlib.h>
    void srand(unsigned int seed);
    

    为了保证我们每次的得到的随机数不一样,我们必须在每次调用时,都确保种子不一样,因此通常会选择使用时间作为种子,注意这只是通常的种子选择,你可以根据实际使用需求进行选择。

    于是我们在使用之前设置好种子,使用示例:

    #include<stdlib.h>
    #include<stdio.h>
    #include<time.h>
    int main(void)
    {
        srand(time(NULL));//设置随机种子,注意只需要设置一次即可
        int i = 0;
        while(i < 5)//生成5个随机数
        {
            printf("%d ",rand());
            i++;
         }
        printf("
    ");
        return 0;
    }
    

    现在好了,每次运行生成的都不一样了。但是还有一个问题,如果这种方式在多线程下使用,也是不可取的,因为rand不是可重入函数。它的每次调用都会修改一些隐藏的属性,因此在多线程中使用它并不合适。

    rand_r

    为了在多线程下使用,我们使用rand_r,使用方式和rand是一样的:

    #include <stdlib.h>
    int rand_r(unsigned int *seedp);
    

    使用示例:

    #include<stdlib.h>
    #include<stdio.h>
    #include<time.h>
    int main(void)
    {
        unsigned int seed = time(NULL);
        int i = 0;
        while(i < 5)//生成5个随机数
        {
            printf("%d ",rand_r(&seed));
            i++;
        }
        printf("
    ");
        return 0;
    }
    

    多线程中,多个线程可能几乎同时调用,那它们的种子可能也一样,如果想不一样,还可以将种子设置成和线程id有关。

    unsigned int seed  = time(NULL)^pthread_self(); 
    

    random

    通过前面的例子可以发现,rand生成的整数范围是有限的,为了生成更大范围,可以使用random:

    #include <stdlib.h>
    long int random(void);
    void srandom(unsigned int seed);
    

    random返回的类型为long int,因此在一定程度上,它生成的范围要大得多。另外与rand类似,需要使用srandom函数设置种子。具体的例子就不再放出了。

    生成指定范围随机数

    前面的例子都是生成[1,RAND_MAX]之间的数,如果要生成指定区间的随机数呢?假设a和b不超过int范围以及它们的差值不超过rand的生成范围。

    [a,b)

    左闭右开区间,即包含a,不包含:

     (rand() % (b - a)) + a;
    

    [a,b]

    左闭右闭,即包含a和b:

     (rand() % (b - a + 1)) + a;
    

    (a,b]

    左开右闭,即不包含a,包含b:

    (rand() % (b-a)) + a + 1;
    

    [0,b]

    rand() % b ;
    

    0到1之间的浮点数

    rand()/(double)RAND_MAX;
    
  • 相关阅读:
    SQL判断如果一列值为null则取另一列值代替 isnull()
    关于js的function.来自百度知道的回答,学习了.
    OSI七层与TCP/IP五层网络架构
    504 Gateway Time-out
    nginx中关于并发数的问题worker_connections,worker_processes
    php实现二叉树的遍历
    nginx负载均衡的简单实现
    linux shell数据重定向
    数据库范式的思考以及数据库的设计
    msyql中myism和innodb的区别
  • 原文地址:https://www.cnblogs.com/Hijack-you/p/12096540.html
Copyright © 2020-2023  润新知