使用friedman检验公式判断这些算法是否性能都相同

4453人阅读
C/C++(1)
本文永久链接为&转载请注明出处
什么叫伪随机数
& & & & 在一些问题中,比如计算机仿真和模拟、密码学等应用中,需要产生一个随机数数列来解决问题。
& & & & 随机数数列分为真随机数数列和伪随机数数列。真随机数数列是完全不可预测的,可以通过放射性衰变、电子设备的热噪音、宇宙射线的触发时间等物理过程得到,但无法通过单纯的软件方式获得;伪随机数数列是可预测的,严格意义上不具有随机性质,通常用数学公式的方法获得。
& & & & 由于很多应用当中对“随机”数列的要求并不十分严格,而且伪随机数的产生较真随机数更为廉价、高效,所以在大多数情况下只要产生统计分布较好的伪随机数数列就能够满足应用要求。早期的伪随机数生成算法以平方取中法为主,现在则以线性同余法为主要方式。下面我会就两种方式分别给出实例,并以数据统计和图形化的方式对伪随机数生成算法的性能进行检验。
& & 正如数列需要有首项,产生伪随机数需要一个初值用来计算整个序列,这个初值被称为“种子”。种子可以是一个固定的值,也可以是根据当前系统状态确定的值。语言用来产生伪随机数的库函数的种子是固定的值,因此每次调用该函数产生的随机数数列都是相同的。所以为了获得随机性更好的数列,种子应为一个变量,该变量可以与当前系统时间、用户对键盘或鼠标操作情况有关。这里我将根据系统时间获得种子。
代码如下:
   #include &time.h&
   unsigned long ssecond,
   long gettime()
//获得当前时间
struct tm *
local=localtime(&t);
local-&tm_mon++;
ssecond=(long)local-&tm_sec*100+local-&tm_sec+36923;
nowtime=local-&tm_sec + local-&tm_min*100 + local-&tm_hour*10000 + local-&tm_mday*1000000 + local-&tm_mon*;
在调用伪随机数生成函数之前通过语句就完成了种子的初始化。
平方取中法
平方取中法是由冯·诺依曼在年提出的,其基本思想为:将数列中的第a(i)项(假设其有m位)平方,取得到的2m位数(若不足2m位,在最高位前补)中间部分的m位数字,作为a(i)的下一项a(i+1),由此产生一个伪随机数数列。即:
x(i+1)=(10^(-m/2)*x(i)*x(i))mod(10^m)
平方取中法计算较快,但在实际应用时会发现该方法容易产生周期性明显的数列,而且在某些情况下计算到一定步骤后始终产生相同的数甚至是零,或者产生的数字位数越来越小直至始终产生零。所以用平方取中法产生伪随机数数列时不能单纯使用公式,应该在计算过程中认为加入更多变化因素,比如根据前一个数的奇偶性进行不同的运算,如果产生的数字位数减少时通过另一种运算使其恢复成m位。
代码如下:
 //编译环境:Code::Blocks 10.05
   //生成的数字范围为[0,LENGTH-1]
   long intlen(long in)
//整数in的长度
long count=0;
while(in!=0)
   long power_10(long in)
//10的in次幂
long i,out=1;
for(i=0;i&i++)
   long rand_pfqz(void)
//平方取中
while(seed&10000)
//保持数位一致
seed=seed*13+seed/10+second/3;
len=intlen(seed);
long temp=
temp=((seed*seed/power_10(len/2))%power_10(len));
if(temp%2==0)
temp+=second/3+7854;
//增加改变因素,
temp+=second*second/2317;
//以延长计算周期
return (unsigned long)(seed%10000*LENGTH)/10000;
以下为在月日时分秒时刻以产生的随机数数列:
93&& 12&& 7&&&& 4&&&& 70&& 32&& 95&& 97&& 25&& 8
49&& 40&& 85&& 63&& 11&& 53&& 65&& 4&&&& 42&& 76
33&& 1&&&& 34&& 88&& 31&& 37&& 79&& 1&&&& 62&& 97
59&& 21&& 6&&&& 47&& 28&& 1&&&& 98&& 60&& 56&& 53
61&& 48&& 47&& 31&& 8&&&& 54&& 53&& 15&& 54&& 67
18&& 6&&&& 46&& 45&& 87&& 44&& 55&& 54&& 46&& 24
74&& 12&& 68&& 41&& 97&& 18&& 27&& 86&& 13&& 81
99&& 74&& 49&& 52&& 69&& 11&& 52&& 89&& 33&& 7
73&& 22&& 1&&&& 95&& 19&& 89&& 57&& 21&& 77&& 90
70&& 87&& 47&& 59&& 19&& 26&& 89&& 32&& 44&& 33
可见,该算法在连续计算次时取到了之间的个不同的数。
LENGTH=500,以连续产生的两个数字作为平面上点的横坐标与纵坐标,计算次,所得图形如下:
线性同余法
& 线性同余方法是目前应用广泛的伪随机数生成算法,其基本思想是通过对前一个数进行线性运算并取模从而得到下一个数。即:
a(i+1)=(a(i)*b+c)mod(m)
其中b称为乘数,c称为增量,m称为模数,它们均为常数。
乘数、增量和模数的选取可以多种多样,只要保证产生的随机数有较好的均匀性和随机性即可。
线性同余法的最大周期是m,但一般情况下会小于m。要使周期达到最大,应该满足以下条件:
(1) c和m互质;
(2) m的所有质因子的能整除b-1;
(3)&若m是4的倍数,则b-1也是;
(4) b,c,a(0)(初值,一般即种子)都比m小;
(5) b,c是正整数。
在C和中都定义有用于产生伪随机数的库函数rand(),而且都是利用线性同余法产生伪随机数。
在中的函数定义如下:
   #define RANDOM_MAX 0x7FFFFFFF
static long do_rand(unsigned long *value)
long quotient, remainder,
quotient = *value / 127773L;
remainder = *value % 127773L;
t = 16807L * remainder - 2836L *
if (t &= 0)
t += 0x7FFFFFFFL;
return ((*value = t) % ((unsigned long)RANDOM_MAX + 1));
  static unsigned long next = 1;
  int rand(void)
return do_rand(&next);
  void srand(unsigned int seed)
//赋初值为种子
在中函数定义如下:
  int __cdecl rand (void)&{
&return(((holdrand = holdrand * 214013L + 2531011L) && 16) & 0x7fff);
C程序设计语言(第二版)(Brian&W.&Kernighan,&Dennis&M.&Ritchie.)中给出了一种适于的函数:
  unsigned long next=1;
  int rand(void)
next=next*+12345;
return (unsigned int)(next/6;
  void srand(unsigned int seed)
     next=
为了提高库函数的性能,可以通过以下函数进行再次运算产生数列:
  int rrand(int n)
return 1+(int)(n*rand()/(RAND_MAX+1));
以下为,利用的库函数产生的随机数序列:
41 67 34 0 69 24 78 58 62 64
5 45 81 27 61 91 95 42 27 36
91 4 2 53 92 82 21 16 18 95
47 26 71 38 69 12 67 99 35 94
3 11 22 33 73 64 41 11 53 68
47 44 62 57 37 59 23 41 29 78
16 35 90 42 88 6 40 42 64 48
46 5 90 29 70 50 6 1 93 48
29 23 84 54 56 40 66 76 31 8
44 39 26 23 37 38 18 82 29 41
可见,该算法在连续计算次时取到了之间的个不同的数。
为了提高算法的均匀性,我找到了一种均匀度非常好的线性同余算法。代码如下:
   //编译环境:Code::Blocks 10.05
   //与平方取中法类似,种子根据当前系统时间获取
   long gettime()
//获得当前时间
struct tm *
local=localtime(&t);
local-&tm_mon++;
nowtime=local-&tm_sec + local-&tm_min*100 + local-&tm_hour*10000 + local-&tm_mday*1000000 + local-&tm_mon*;
   #define LENGTH 100
   //生成的数字范围为[0,LENGTH-1]
  int rand_xxty(void)
//线性同余法
seed=(unsigned long)(seed*101+81)%LENGTH;
return (int)
以下为在月日时分秒时刻以产生的伪随机数:
56 37 18 99 80 61 42 23 4 85
66 47 28 9 90 71 52 33 14 95
76 57 38 19 0 81 62 43 24 5
86 67 48 29 10 91 72 53 34 15
96 77 58 39 20 1 82 63 44 25
6 87 68 49 30 11 92 73 54 35
16 97 78 59 40 21 2 83 64 45
26 7 88 69 50 31 12 93 74 55
36 17 98 79 60 41 22 3 84 65
46 27 8 89 70 51 32 13 94 75
可见,该算法在连续计算次时取到了之间的所有的数。
LENGTH=500,以连续产生的两个数字作为平面上点的横坐标与纵坐标,计算次,做出图形,可以看出该方法的特点,以及均匀性好的原因了:
从数据统计和所绘图形来看,该算法有极好的均匀性,但规律性较强,随机性较差,适合应用在对均匀度要求较高,而对随机性要求不高的问题中。
以上给出的几种伪随机数生成算法各有优势,而且性能都能达到一般应用的要求,具有一定的实用价值。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:18907次
排名:千里之外
--------------------------------------------------
(1)(1)(1)(3)(1)关注今日:36 | 主题:184059
微信扫一扫
扫一扫,下载丁香园 App
即送15丁当
这个表的数据是用Kruskal-Wallis H 检验还是Friedman检验啊?或者是用其他什么检验方法?在spss怎么操作?拜托啦,不懂检验
页码直达:
问题已关闭悬赏丁当:5
不知道邀请谁?试试他们
微信扫一扫
广告宣传推广
政治敏感、违法虚假信息
恶意灌水、重复发帖
违规侵权、站友争执
附件异常、链接失效
丁香园准中级站友
取决于目的,如果目的在于三组间有没有差别,就用Kruskal-Wallis H, 如果是比较每组自身内部这三次有没有变化,就用Friedmann。
微信扫一扫
广告宣传推广
政治敏感、违法虚假信息
恶意灌水、重复发帖
违规侵权、站友争执
附件异常、链接失效
在spss上怎么输入数据啊?怎么弄的
微信扫一扫
广告宣传推广
政治敏感、违法虚假信息
恶意灌水、重复发帖
违规侵权、站友争执
附件异常、链接失效
关于丁香园工具类服务
编辑部专用服务
作者专用服务
基于神经网络的假设检验故障诊断算法研究
传统的χ2检验法通过比较先验信息与量测信息进行故障检测,当先验信息所依赖的模型出现错误时将无法进行有效的故障检测和故障隔离.提出利用神经网络的方法结合χ2检验法进行故障诊断,训练神经网络来跟踪系统模型,则正确的先验信息保存在训练好的神经网络中,系统模型输出与网络模型输出之差作为故障诊断的依据.针对INS/GPS组合导航系统进行算法仿真,该算法能够快速、准确地判断系统故障源,通过故障隔离和系统重构,使系统在故障情况下依然保持正常工作.
ZANG Rong-chun
CUI Ping-yuan
作者单位:
哈尔滨工业大学深空探测基础研究中心,黑龙江,哈尔滨,150001
年,卷(期):
机标分类号:
在线出版日期:
基金项目:
国家高技术研究发展计划(863计划)
本文读者也读过
相关检索词
万方数据知识服务平台--国家科技支撑计划资助项目(编号:2006BAH03B01)(C)北京万方数据股份有限公司
万方数据电子出版社

我要回帖

更多关于 friedman 事后检验 的文章

 

随机推荐