rand()如何工作? 它有一定的倾向吗? 有什么更好的使用?
我已经读过,它与时间有关,也包括time.h,所以我假设了很多,但它是如何工作的? 另外,它是否有任何倾向于奇数或偶数或类似的东西? 最后是在C标准库还是基础框架中有更好的分布?
简述:
-
你使用
time.h
来获得一个种子,这是一个初始的随机数。 然后C对这个数字进行一系列的操作,得到下一个随机数,然后对那个数进行操作,得到下一个,然后…你得到的图片。 -
rand()
能够触及每一个可能的整数。 不pipeinput种子如何,它都不会喜欢偶数或者奇数。 尽pipe如此,它还是有局限性的 – 它会相对快速地重演,几乎在每个实现中只能给出32767的数字。 -
C没有另外的内置随机数发生器。 如果你需要一个真正的难题 ,网上有很多软件包,但是Mersenne Twisteralgorithm可能是最受欢迎的select。
现在,如果你对上述的理由感兴趣,下面是关于rand()
如何工作的细节:
rand()
就是所谓的“ 线性同余发生器” 。 这意味着它使用了一个forms的等式:
x n + 1 =( * a **** x n + *** b * )mod m
其中x n是第n 个随机数,并且a和b是一些预定的整数。 算术模m执行,其中m取决于机器通常是2 32 ,因此在计算x n + 1时只保留最低32位。
在英文中,这个想法是这样的:为了得到下一个随机数,把最后一个随机数乘以某个东西,给它添加一个数字,然后取最后的几个数字。
一些限制很快就会显现出来:
-
首先,你需要一个开始的随机数字。 这是你的随机数发生器的“种子”,这是你听说过使用
time.h
地方。 既然我们需要一个真正的随机数,那么询问系统是什么时间(以整数forms)并将其用作第一个“随机数”是常见的做法。 另外,这解释了为什么使用相同的种子两次总是会给出完全相同的随机数序列。 这听起来很糟糕,但实际上是有用的,因为当你控制你的程序的input时,debugging更容易 -
其次,必须非常小心地selecta和b ,否则会得到一些灾难性的结果。 幸运的是,线性同余发生器的方程很简单,所以math已经被详细解释了。 事实certificate,select一个满足* a *** mod8 = 5和*** b * = 1的a将确保所有m个整数都是相等的可能性,与种子的select无关。 你也需要一个非常大的值,所以每当你乘以x n时,就会触发一个模数,并切掉很多数字,否则连续的许多数字将会是对方的倍数。 结果,根据Knuth, a (例如)的两个常见值是1566083941和1812433253。 GNU C库碰巧使用a = 1103515245和b = 12345。 LCG的维基百科页面提供了大量实现的值列表。
-
第三,线性同余发生器实际上会因为这个模而重复。 这成为一些非常令人兴奋的math,但是结果都是非常简单的:在生成了m个数字之后,序列会重复。 在大多数情况下,这意味着你的随机数发生器将每2 32个周期重复一次。 这听起来很多,但它确实不适用于许多应用程序。 如果你正在用蒙特卡洛模拟进行严肃的数值工作,这个数字是绝望的不足。
-
第四个不太明显的问题是数字实际上并不是真正的随机数。 他们有一个有趣的相关性。 如果从具有a和m的某个值的LCG中取三个连续的整数( x , y , z ),这三个点总是落在由三个点的所有线性组合产生的点的格上(1,a ,a 2 ),(0,m,0),(0,0,m)。 这就是所谓的马萨利亚定理,如果你不明白,那没关系。 所有这一切意味着:LCG中随机数字的三元组将在某个深层次上显示相关性。 通常这对你或我来说太深了,但是它在那里。 如果给出第二个和第三个数字,甚至可以用三个数字的“随机”序列重构第一个数字! 这根本不适合encryption。
好的部分是像rand()
这样的LCG是非常非常小的占位面积。 它通常只需要32位保持状态,这真的很好。 这也是非常快,需要很less的操作。 这些对于非关键的embedded式系统,video游戏,休闲应用程序等都是很好的select。
PRNGs是一个引人入胜的话题。 如果你渴望了解更多关于历史或今天的各种实现, 维基百科总是一个很好的去处。
rand
返回由伪随机数生成器 (PRNG)生成的数字 。 它返回的数字序列是确定性的,基于PRNG初始化的值(通过调用srand
)。
这些数字应该是分布的,使得它们看起来有些随机,所以,例如,奇数和偶数应该以大致相同的频率返回。 随机数发生器的实际实现是不确定的,所以实际的行为是特定于实现的。
要记住的重要一点是rand
不会返回随机数; 它返回伪随机数,它返回的值由种子值和rand
被调用的次数决定。 这种行为在许多用例中都是正确的,但不适用于其他用例(例如, rand
在许多encryption应用程序中不适用)。
rand()如何工作?
http://en.wikipedia.org/wiki/Pseudorandom_number_generator
我已经读过,它与时间有关,也包括time.h
rand()
与时间无关。 但是,使用time()
来获取PRNG的“种子”是很常见的,这样每次运行程序时都会得到不同的“随机”数字。
另外,它是否有任何倾向于奇数或偶数或类似的东西?
取决于使用的确切方法。 rand()
有一个stream行的实现,在奇数和偶数之间交替 。 所以避免编写像rand() % 2
这样的代码,这个代码依赖于最低位是随机的。