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

时间:2018-01-26 00:24:17

标签: c random distribution

该手册页声称C标准库中的random函数“返回0到RAND_MAX之间的值。”

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

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

2 个答案:

答案 0 :(得分:8)

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

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

一般情况下,我认为如果您承诺在某个范围内生成随机数字,则假设(当数字的数量变为无穷大时)它们应累积到均匀分布,否则你失去了一些随机性(失去熵)。根据我的经验,你唯一一次提到随机数生成器的分布是因为它不是统一的(例如,他们可能会告诉你某些特定的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但已被移植到其他系统 - 它被定义为产生均匀分布。

答案 1 :(得分: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。

     

NB:   暂时将此函数定义为返回a   int32_t   值表示   即使返回值总是包含32位   长整数   更广泛。标准   要求它不同。但用户必须始终了解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&lt; = size&lt; 32调用initstate(),则random()使用简单的线性同余随机数生成器。

     

初始化状态后,setstate()允许在状态数组之间切换。 state参数定义的数组用于进一步生成随机数,直到调用initstate()或再次调用setstate()。 setstate()函数返回指向前一个状态数组的指针。

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

从第330页起:

  

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

这些也是defined by POSIX