如何评价一个伪随机数生成算法的优劣

以下来自我在知乎的回答。http://www.zhihu.com/question/20222653

谈到随机性,这大概是一个令人困惑哲学问题吧。随机行为精确地说究竟指的是什么,最好是有定量的定义。Kolmogorov曾提出一种判定随机性的方法:
对于无穷的随机数序列,无法用其子序列描述。J.N.Franklin则认为:如果一个序列具有从一个一致同分布的随机变量中独立抽样获得的每个无限序列
都有的性质,则是随机的。这些定义都不是很精确,有时甚至会导致矛盾。可见数学家在谈到这个问题时是多么的审慎。
随机数生成器只是一种产生符合特
定分布的随机数的算法。这些所谓的随机数序列实际上是周期性的。从实用的角度出发,随机数生成器如果能够在尽可能多的场合中产生正确的结果,那么它就是好
的。但是这个愿望无法完全实现。因为每一个生成器都会在特定的场合失效,比如说可能无法达到随机数的均匀性或者随机数之间隐藏着关联。
已经有大量的随机数生成器,但是找到好的、易移植的、达到工业水准的随机数生成器是一个难以实现的目标。生成非均匀分布的标准方法是先产生均匀分布随机数,然后将其转化为特定分布的随机数。我在博客关于随机数的笔记中有简易介绍。Knuth曾经说

. . . look at the subroutine library of each computer installation
in your organization, and replace the random number generators by good ones.
Try to avoid being too shocked at what you find.

对于不同的应用,这些因素的重要程度并不一样。比如说用物理方法产生的真随机数比由数学方法产生的伪随机数随
机性更强,更难破解,但这并不能说明物理方法产生的随机数质量更高。假设我们并能够事先知道应用的场景,应该如何评价一个生成器的质量呢?我们并不知道采
样的过程、样本的大小或者仿真中的维度。以下两点是很重要的:

  1. 生成器只提供预测,不提供保证。这是因为我们产生的只是有限数量的随机数,并且转换成特定分布的方法并不是足够好。因此,在特定的场合即使可靠的生成器也会失效。

  2. 尽管没有保证,但是有数学上的安全性测度。这意味着我们可以从理论上知道周期长度、一些结构性质以及关联性等。周期长度会限制样本的大小;结构信息可以是我们确定在仿真中是否存在副作用;关联性质则对随机模拟而言很重要。

不言而喻,随机数生成的方法应是快速的,占用内存少的,实现简单,可移植,可并发执行,对于不同的参数都应当具有均匀的速度。更加重要的检测内容是对其统计性质的检测。统计检验又分为两类:一类是理论检验,另一类是经验检验。

来说说理论检验。顾名思义,理论检验是先验的检验,能够预先告诉我们这些检验的结果将会是如何。如前所述,理论检验主要是检验随机数的周期,内在结构和关
联性。发展这一类型的理论十分困难,至今的得到的结果一般是对整个周期的统计检验。对于线性同余算法得到的随机数,周期长度的平方根是一个比较好的样本大
小的上限。因此对于一个好的生成器,必须能够使得对于某些参数能够得到最大的周期长度,并且能够计算出这样的参数。比如对于线性同余算法而言,最好的乘数 是,模是.这个观点在很多书籍和论文中都有推荐,但是随着计算机计算能力的提高,这个观点已经不合时宜啦。因为对于现代的计算机而言,这样的周期还是太短了,现在而言m不应小于.生成器的内部结构如栅栏结构和超平面点的分布也很重要。对于不同的生成器有特定的检测方法。结构检测用到最多的就是谱检验,谱检验就是基于相邻平行超平面之间最大距离的检验,该距离越大,生成器越大。如下图所示:

上图中随机数主要保持在平面内。
对于二维的情况如下图所示:

上图中我们可以用少量的平行线来全部覆盖它们,由许多不同的平行线族,它们将会碰上所有的点。平行覆盖线的数目是一个重要的指标。
将随机数生成器应用在并行进程中尤其要注意的是随机数之间是否关联,即独立性检测。比如用线性同余算法得到的均匀分布经Box-Muller转换成正态分布得到的点落在一条螺旋线上,如下图:


理论上可以证明所有的线性和非线性同余序列都存在长周期相关现象。如果几个并行处理器分别使用同一个同余序列的不同段落,分割时就应该避开具有强相关的分
点。以上的3副图给人一种触目惊心的感觉,没想到我们平常用到最多的线性同余算法产生的随机数是如此的”不随机“,我想这种震撼类似于第一次用显微镜观察
微生物发现一个不可思议的微观世界。的确,这类似于我们用超高分倍率的显微镜来观察我们得到的随机数,只有对于很精确的应用情境这种观察才是有价值的,否
则只是杞人忧天、庸人自扰了。在这种情况下,简单的线性同余序列肯定是不适用的,应当使用具有更大周期的生成序列,尽管实际上只要生成这个周期中的很小的
一部分。

理论检验是不够的,我们还需要经验检验。经验检验性对较简单,且有很多的方法。比如:

  1. 等分布检验:又称均匀性检验,将【0,1[】区间分成k个相等的子区间,落在每个子区间的伪随机数个数应该相等。常用的是检验。

  2. 序列检验:相继的数偶独立一致分布。计算的是数偶对的出现次数。

  3. 间隔检验:用来考察在某个范围内序列的出现的间隔长度。

  4. 扑克检验:考虑5个相继整数组成的n个组,观察其出现模式。

  5. ........

经验检验还有很多,不一一赘述了。

当然即使通过了所有的统计测试,这也不能证明什么,但是这提高了我们使用这个生成器的信心。

于实际应用中,应该对不同的应用场景选择合适的生成器。当然也有一些通用的测量方法来告诉我们该生成器是否有可能是一个好的生成器。对于并行应用来说,很
多通常情况下很好的生成器都不合适。我们可以为k个进程选择k个生成器,虽然这也不是一个很好的方法。通用的方法如下:

有一个比喻:随机数生成器就像抗生素,每一种都有副作用,没有安全的随机数生成器。好的随机数生成器应该是有理论检验的支持,充分的经验证据和良好的实际表现。遵循以下一些建议对于合理使用随机数生成器很有帮助:

  1. 不要相信只由一个生成器得到的随机数序列,在使用前用不同的生成器检验它们的结果。

  2. 不要在没有理论依据和经验支持的情况下将几种生成器结合起来或并行。

  3. 在使用前了解生成器的特性。

如何评价一个伪随机数生成算法的优劣,码迷,mamicode.com

时间: 2024-12-18 22:11:35

如何评价一个伪随机数生成算法的优劣的相关文章

Redis源码中看伪随机数生成算法

导读 --------------------------------------------------------------------------------------------------------------------------------------------------------------         Redis源码中有一个rand.c的源文件,很明显这是一个和(伪)随机数有关的文件.细看该文件代码只有寥寥50行,不过涉及到的算法原理却不简单,读起来虽然有些晦

如何开发一个异常检测系统:如何评价一个异常检测算法

利用数值来评价一个异常检测算法的重要性 使用实数评价法很重要,当你用某个算法来开发一个具体的机器学习应用时,你常常需要做出很多决定,如选择什么样的特征等等,如果你能找到如何来评价算法,直接返回一个实数来告诉你算法的好坏,那样你做决定就会更容易一些.如现在有一个特征,要不要将这个特征考虑进来?如果你带上这个特征运行你的算法,再去掉这个特征运行你的算法,得到返回的实数,这个实数直接告诉你加上这个特征算法是变好了还是变坏了,这样你就有一种更简单的算法来确定是否要加上这个特征. 为了更快地开发出一个异常

又是一个渐变色生成算法

背景 简化了下背景,给定一个指标X,比较小的时候是正常的,比较大的时候比较危险.为了更直观地地显示,前端显示的时候希望使用颜色来高亮这个值——比较小的时候颜色是绿色,较大的时候显示红色,并且用一些黄色进行过渡. 使用google搜了搜,没有找到合适的代码.于是乎,露珠自己打算搞个~贻笑大方了··· 分析 颜色在HTML中可以用RGB值来表示——绿色是rgb(0,255,0), 红色是rgb(255,0,0),黄色是rgb(255,255,0). 为了达到渐变效果,需要设计一个函数F: F(0)

伪随机数生成算法

常用方法为线性同余法 初始值有4个整数,模数m,乘数a,增量c,种子s 2<=a<m,0<=c<m,0<=s<m xn = (axn-1+c)mod m 实际使用中m和a的值都取得比较大 其中一组为 m = 232 - 1,a = 75  = 16807,c = 0

一个简单的伪随机数发生算法(转)

源:一个简单的伪随机数发生算法 //此代码纯属交流目的,如用作安全领域,后果自负 #include <stdint.h> #include <stdlib.h> //! \brief random seed static uint16_t s_hwRandomSeed = 0xAA55; static uint8_t s_chRandomTable[] = { 0x12,0x23,0x45,0x67,0x89,0xAB,0xCD,0xEF, 0xF1,0xE2,0xD3,0xC4,

[计算机漫谈]伪随机数生成方法

大家好.今天说点儿关于程序设计过程中产生随机数的方法. (一)JAVA伪随机数生成方法 随机数在程序设计过程中,特别是在实践环境模拟和测试等领域中得到很广泛的应用,我们在编程的过程中也时不时需要使用到随机数.计算机中的随机数,并不是真正的随机数,而是叫做"伪随机数",是计算机通过某种特别算法模拟产生的. 在JAVA语言中,我们可以通过Math类的random方法产生区间[0,1)的随机数,若要产生[a,a+b)之间的伪随机数,可以通过语句 a + b * Math.random();

伪随机数生成方法

大家好.今天说点儿关于程序设计过程中产生随机数的方法. (一)JAVA伪随机数生成方法 随机数在程序设计过程中,特别是在实践环境模拟和测试等领域中得到很广泛的应用,我们在编程的过程中也时不时需要使用到随机数.计算机中的随机数,并不是真正的随机数,而是叫做"伪随机数",是计算机通过某种特别算法模拟产生的. 在JAVA语言中,我们可以通过Math类的random方法产生区间[0,1)的随机数,若要产生[a,a+b)之间的伪随机数,可以通过语句 a + b * Math.random();

微博URL短网址生成算法原理及(java版、php版实现实例)

短网址(Short URL),顾名思义就是在形式上比较短的网址.通常用的是asp或者php转向,在Web 2.0的今天,不得不说,这是一个潮流.目前已经有许多类似服务,借助短网址您可以用简短的网址替代原来冗长的网址,让使用者可以更容易的分享链接. 例如:http://t.cn/SzjPjA 短网址服务,可能很多朋友都已经不再陌生,现在大部分微博.手机邮件提醒等地方已经有很多应用模式了,并占据了一定的市场.估计很多朋友现在也正在使用. 看过新浪的短连接服务,发现后面主要有6个字符串组成,于是第一个

记一次随机字符串生成算法的随机概率与性能的提升

一.前言背景 前几天我部门一个和银行对接的项目中出现了业务Id重复的现象,导致了很多之前不可预见的bug.由于该项目有资金流动,涉及到金钱交易,故不敢有任何闪失.于是leader把同事写的Handler.ashx.cs发给我瞧了瞧,其中的一处流水号生成代码引起了我的注意.代码如下: string[] str1 = new string[] { "A", "B", "C", "D", "E", "F