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

What is the distribution for random() in stdlib?

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

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

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

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

它记录在 glibc documentation and in POSIX 中。但是,任何一个文本都不能保证分发。

glibc:

long int random(void)

Preliminary:|MT-Safe|AS-Unsafe lock|AC-Unsafe lock|SeeSection 1.2.2.1[POSIX Safety Concepts], page 2.

This function returns the next pseudo-random number in the sequence. The value returned ranges from 0 to 2147483647.

NB: Temporarily this function was defined to return a int32_t value to indicate that the return value always contains 32 bits even if long int is wider. The standard demands it differently. Users must always be aware of the 32-bit limitation, though.

POSIX:

The random() function uses a non-linear additive feedback random-number generator employing a default state array size of 31 long integers to return successive pseudo-random numbers in the range from 0 to 2^31-1. The period of this random-number generator is approximately 16 x (2^31-1). The size of the state array determines the period of the random-number generator. Increasing the state array size increases the period.

With 256 bytes of state information, the period of the random-number generator is greater than 2^69.

Like rand(), random() produces by default a sequence of numbers that can be duplicated by calling srandom() with 1 as the seed.

The srandom() function initialises the current state array using the value of seed.

The initstate() and setstate() functions handle restarting and changing random-number generators. The initstate() function allows a state array, pointed to by the state argument, to be initialised for future use. The size argument, which specifies the size in bytes of the state array, is used by initstate() to decide what type of random-number generator to use; the larger the state array, the more random the numbers. Values for the amount of state information are 8, 32, 64, 128, and 256 bytes. Other values greater than 8 bytes are rounded down to the nearest one of these values. For values greater than or equal to 8, or less than 32 random() uses a simple linear congruential random number generator. The seed argument specifies a starting point for the random-number sequence and provides for restarting at the same point. The initstate() function returns a pointer to the previous state information array.

If initstate() has not been called, then random() behaves as though initstate() had been called with seed=1 and size=128.

If initstate() is called with 8 <= size <32, then random() uses a simple linear congruential random number generator.

Once a state has been initialised, setstate() allows switching between state arrays. The array defined by the state argument is used for further random-number generation until initstate() is called or setstate() is called again. The setstate() function returns a pointer to the previous state array.

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

从第 330 页开始:

The functions lrand48() and nrand48() return non-negative long integers uniformly distributed over the interval [ 0 , 2^31).

这些也是defined by POSIX

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

我认为可以非常安全地假设,对于您遇到的计算机,random()rand() 将产生 运行dom 数字,这些数字累积到(大约)均匀分布,但是,如果您不确定,可以根据经验进行测试。

一般来说,我认为如果你承诺在运行ge中生成一个运行dom号码,假设(作为数量数字趋于无穷大)它们应该累积成均匀分布,否则你会失去一些 运行domness(熵损失)。根据我的经验,你唯一一次提到 运行dom 数字生成器的分布是不是统一的(例如,他们可能会告诉你某些特定的 PRNG 会根据以下内容生成 运行dom 数字正态分布)。

编辑(POSIX)

在验证我的假设时,我 运行 跨越 POSIX 函数族,这些函数被定义为在均匀分布中生成 运行dom 数字:

NAME

drand48, erand48, jrand48, lcong48, lrand48, mrand48, nrand48, seed48, srand48 - generate uniformly distributed pseudo-random numbers

SYNOPSIS

#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 does note that they are not cryptographically secure, and that arc4random() 用于加密应用程序。 arc4random() 来自 BSD,但已移植到其他系统 -- 它被定义为产生统一分布。