首页 文章

stdlib中random()的分布是什么?

提问于
浏览
4

该手册页声称C标准库中的random函数"returns a value between 0 and RAND_MAX."

不幸的是,它没有说明这个随机函数的分布是什么 . 根据经验,我们可以测量它是统一的,但是没有文档,我不能肯定当我在应用程序中使用它时它永远不会改变 .

分发是否记录在任何地方?

2 回答

  • 3

    random(void) 函数不是C标准的一部分 . 但是,(@ nwellnhof!)它是POSIX标准的一部分 .

    它记录在glibc documentationPOSIX中 . 但是,任何一种文本都不能保证分发 .

    glibc的:

    long int random(void)初步:| MT-Safe | AS-Unsafe lock | AC-Unsafe lock |见第1.2.2.1节[POSIX安全概念],第2页 . 此函数返回序列中的下一个伪随机数 . 返回的值范围为0到2147483647.注意:暂时将此函数定义为返回int32_t值,以指示返回值始终包含32位,即使long int更宽 . 标准要求不同 . 但是,用户必须始终了解32位限制 .

    POSIX:

    random()函数使用非线性加法反馈随机数生成器,使用31个长整数的默认状态数组大小来返回0到2 ^ 31-1范围内的连续伪随机数 . 该随机数发生器的周期约为16 x(2 ^ 31-1) . 状态数组的大小决定了随机数发生器的周期 . 增加状态数组大小会增加周期 . 利用256字节的状态信息,随机数发生器的周期大于2 ^ 69 . 与rand()一样,random()默认生成一系列数字,可以通过调用srandom()并将1作为种子来复制 . srandom()函数使用seed的值初始化当前状态数组 . initstate()和setstate()函数处理重启和更改随机数生成器 . initstate()函数允许初始化state参数指向的状态数组以供将来使用 . size参数指定状态数组的字节大小,initstate()使用它来决定使用哪种类型的随机数生成器;状态数组越大,数字越随机 . 状态信息量的值是8,32,64,128和256字节 . 大于8个字节的其他值将向下舍入到这些值中最接近的一个值 . 对于大于或等于8或小于32的值,random()使用简单的线性同余随机数生成器 . seed参数指定随机数序列的起始点,并提供在同一点重新启动 . initstate()函数返回指向前一个状态信息数组的指针 . 如果尚未调用initstate(),则random()的行为就像使用seed = 1和size = 128调用initstate()一样 . 如果使用8 <= size <32调用initstate(),则random()使用简单的线性同余随机数生成器 . 初始化状态后,setstate()允许在状态数组之间切换 . state参数定义的数组用于进一步生成随机数,直到调用initstate()或再次调用setstate() . setstate()函数返回指向前一个状态数组的指针 .

    但是,如果您正在使用GLIBC,并且您希望标准保证的伪随机数函数在其范围内生成均匀分布的随机数,那么您可以使用SVID random functionslrand48 和朋友:

    从第330页起:

    函数lrand48()和nrand48()返回在区间[0,2 ^ 31]上均匀分布的非负长整数 .

    这些也是defined by POSIX .

  • 8

    C标准和POSIX规范都没有定义 random()rand() 的分布 . 我检查的一些系统的联机帮助页似乎也没有定义 .

    我认为用您遇到的计算机来假设 random()rand() 会产生随机数累积到(近似)均匀分布是非常安全的,但如果您不确定,可以凭经验测试 .

    一般来说,我认为如果你承诺在一个范围内生成 random 数字,则假设(当数字的数量变为无穷大时)它们应该累积到均匀分布,否则你会失去一些随机性(失去熵) . 根据我的经验,你唯一一次提到随机数生成器的分布是否是统一之外的东西(例如,他们可能会告诉你某些特定的PRNG会根据正态分布产生随机数) .

    编辑(POSIX)

    在验证我的假设时,我遇到了一个POSIX函数系列,这些函数被定义为以统一分布生成随机数:

    NAME drand48,erand48,jrand48,lcong48,lrand48,mrand48,nrand48,seed48,srand48 - 生成均匀分布伪随机数概要#include <stdlib.h>

    double drand48(void);
    double erand48(unsigned short xsubi [3]);
    long jrand48(unsigned short xsubi [3]);
    void lcong48(unsigned short param [7]);
    long lrand48(void);
    long mrand48(void);
    long nrand48(unsigned short xsubi [3]);
    unsigned short * seed48(unsigned short seed16v [3]);
    void srand48(long seedval);

    FreeBSD的manpage for drand48确实注意到它们不具有加密安全性,并且建议将arc4random()用于加密应用程序 . arc4random() 来自BSD但已被移植到其他系统 - 它被定义为产生均匀分布 .

相关问题