rand()如何工作?它有一定的倾向吗?有没有比这更好用的东西?

Reg*_*an 9 c random objective-c

我已经读过它与时间有关,你也可以从包含time.h开始,所以我假设了很多,但它是如何工作的呢?此外,它是否有任何倾向于奇数或偶数或类似的东西?最后是在C标准库或Foundation框架中有更好的分发吗?

spe*_*son 21

简述:

  • time.h用来获取种子,这是一个初始随机数.C然后对这个数字进行一系列操作以获得下一个随机数,然后对该数字进行操作以获得下一个,然后......你得到了图片.

  • rand()能够触及每个可能的整数.不管输入的种子如何,它都不会喜欢偶数或奇数.尽管如此,它仍有限制 - 它会相对较快地重复,并且在几乎每个实现中只提供高达32767的数字.

  • C没有其他内置随机数生成器.如果你需要一个非常艰难的一个,网上有很多软件包,但Mersenne Twister算法可能是最受欢迎的选择.

现在,如果你有兴趣的原因,为什么上面是真实的,下面是关于如何骇人听闻的细节rand()工作:

rand()就是所谓的" 线性同余发生器".这意味着它采用了以下形式的等式:

x n + 1 =(*a****x n +***b*)mod m

其中x n是第n 随机数,ab是一些预定的整数.运算执行模,与通常为2 32根据在机器上,使得只有最低32位被保存在x的计算N + 1.

那么,在英语中,想法是这样的:要获得下一个随机数,将最后一个随机数乘以某个东西,为其添加一个数字,然后取最后几个数字.

一些限制很快就会明显:

  • 首先,您需要一个起始随机数.这是随机数生成器的"种子",这是您听说过time.h使用的地方.由于我们需要一个非常随机的数字,因此通常的做法是询问系统的时间(以整数形式)并将其用作第一个"随机数".此外,这解释了为什么两次使用相同的种子将始终给出完全相同的随机数序列.这听起来很糟糕,但实际上很有用,因为当你控制程序的输入时,调试会容易得多

  • 其次,必须非常非常仔细地选择ab,否则你会得到一些灾难性的结果.幸运的是,线性同余生成器的等式很简单,数学已经详细计算出来了.事实证明,选择一个一个满足*一个***mod8 = 5连同***B* = 1将确保所有整数是同等可能的,独立的种子的选择.你也想的值一个是真正的大,所以,每次你用X乘以ñ你触发模和砍掉了很多的数字,否则许多数字在一排也只是彼此的倍数.其结果是,两者的共同值(例如)根据Knuth的说法是1566083941和1812433253.GNU C库碰巧使用a = 1103515245和b = 12345.许多实现的值列表可以在维基百科页面上找到.

  • 第三,由于该模数,线性同余生成器实际上将重复自身.这可能是一些非常令人兴奋的数学,但结果却非常简单:序列将在生成m个数之后重复.在大多数情况下,这意味着您的随机数生成器将每2 32个周期重复一次.这听起来很多,但它确实不适用于许多应用程序.如果您正在使用蒙特卡罗模拟进行严肃的数值工作,那么这个数字绝对不足.

  • 第四更明显的问题是,该数字实际上不是真正随机的.他们有一种有趣的相关性.如果从具有某个值am的LCG中取三个连续的整数(x,y,z),则这三个点将始终落在由三个点的所有线性组合生成的点的晶格上(1,a ,2),(0,m,0),(0,0,m).这被称为Marsaglia的定理,如果你不理解它,那没关系.所有这一切都意味着:来自LCG的随机数的三元组将在某个深层,深层显示相关性.通常它对你或我来说都太深了,但它在那里.如果给出第二个和第三个数字,甚至可以在三个数字的"随机"序列中重建第一个数字!这根本不适用于密码学.

好的部分是LCG像rand()非常非常低的占地面积.它通常只需要32位来保持状态,这非常好.它也非常快,只需要很少的操作.这些非常适合非关键的嵌入式系统,视频游戏,休闲应用程序等.

PRNG是一个引人入胜的话题.如果您渴望了解有关历史或今天各种实施的更多信息,维基百科始终是一个好去处.

  • GCC没有"使用"任何`rand()`的实现.GCC是一个编译器,`rand()`由主机系统的libc提供.gnu libc可以跨平台使用特定实现. (2认同)

Jam*_*lis 10

rand返回伪随机数生成器(PRNG)生成的数字.它返回的数字序列是确定性的,基于PRNG初始化的值(通过调用srand).

数字应该被分配,使得它们看起来有些随机,因此,例如,奇数和偶数应该以大致相同的频率返回.随机数生成器的实际实现未指定,因此实际行为特定于实现.

要记住的重要一点是rand不返回随机数; 它返回伪随机数,它返回的值由种子值和rand已调用的次数决定.这种行为适用于许多用例,但不适合其他用例(例如,rand不适合在许多加密应用程序中使用).