找回密码
 欢迎注册
查看: 16898|回复: 13

[讨论] HugeCalc的随机数算法有多可靠?

[复制链接]
发表于 2010-2-27 11:38:44 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?欢迎注册

×
随机数使用了什么算法?该算法有多可靠?请给出相关的定理。
千万别回答我相当可靠之类的话,我基本上不相信别人,只相信定理。

随机数产生的结果和哪些因素有关?和硬盘之类的因素有关吗?
似乎加密软件的随机数的种子的产生之前,还要不断地晃动鼠标。

还有就是随机数的产生周期之类的问题,似乎MATLAB的产生
重复的随机数的周期特别大,以致于宇宙毁灭掉都不会产生重复
的随机数。

在这里也可以讨论讨论随机数的产生的算法之类的问题
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2010-2-27 11:39:40 | 显示全部楼层
pari/gp的随机数的产生周期也很长,具体我忘记了
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2010-2-27 12:31:02 | 显示全部楼层
随机数产生跟晃动鼠标有什么关系吗?
随机数产生跟时间应该有关系吧
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2010-2-27 12:46:20 | 显示全部楼层
随机数的产生跟时间也应该无关系吧
只是我们平时都喜欢把程序运行的当前时间作为种子。。。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2010-2-27 13:21:34 | 显示全部楼层
晃动鼠标时,鼠标指针的坐标参数变化是一列性质良好的随机数。

这列随机数的产生速度比抛硬币、投骰子快多了

千万别用C++标准库里自带的rand()函数,这个rand()函数太挫了。

比如下面这段代码……
  1. #include<cstdio>
  2. #include<cstdlib>

  3. int rand16()        //生成一个0到15的随机数
  4. {
  5.         return rand()%16;
  6. }

  7. char rand_ch()        //把两个0到15的随机数拼成一个字节
  8. {
  9.         return rand16()*16+rand16();
  10. }

  11. int main(int i)
  12. {
  13.         freopen("d:\\rand.txt","wb",stdout);
  14.         for(i=0;i<16777216;i++)        //输出16M字节
  15.                 printf("%c",rand_ch());
  16.         return 0;
  17. }
复制代码
生成的16MB的文件拿winRAR软件压缩一下就只剩522KB了,说明rand()生成的随机数很糟糕。

难怪拿去做各种不确定性试验时,出现一连串雷同的试验结果。

如果说一个随机数列是好的,那么它:

每一项的取值都是分布均匀的;
相邻两项组成的二元组是分布均匀的;
相邻三项组成的三元组是分布均匀的;
……
相邻N项组成的N元组是分布均匀的。

如果上述条件有一个不满足,就说明这个数列的熵值未达到最大,可以用哈夫曼编码进行压缩。

WinRAR软件已经在一定程度上实现了这一功能,所以可以根据WinRAR软件的压缩结果来衡量一个随机数列的好坏。

对于好的随机数列,其熵值一定是最大化的,WinRAR软件是一个字节都压不动的。

要加长随机数列的周期,可以通过添加辅助变量的方法。

把上述代码修改如下:
  1. #include<cstdio>
  2. #include<cstdlib>

  3. unsigned int s;        //辅助变量

  4. int rand16()        //生成一个0到15的随机数
  5. {
  6.         s=s*s+s/13+rand();
  7.         return s%16;
  8. }

  9. char rand_ch()        //把两个0到15的随机数拼成一个字节
  10. {
  11.         return rand16()*16+rand16();
  12. }

  13. int main(int i)
  14. {
  15.         freopen("d:\\rand.txt","wb",stdout);
  16.         for(i=0;i<16777216;i++)        //输出16M字节
  17.                 printf("%c",rand_ch());
  18.         return 0;
  19. }
复制代码
虽然只做了小小的改动,但生成出来的16MB的文件用winRAR压缩,一个字节都压不动了。

因为添加辅助变量后,即使rand()函数跑完了一个周期,但辅助变量的值与初值不同,所以生成出来的数是不同的。

要等到rand()函数跑完了一个周期的同时,辅助变量恰好回到原始初值,才是一个完整的周期。

显然这个周期远比单独使用rand()函数的周期长。

添加辅助变量需要额外的运算量。

所以要根据实际的需要来选取合适的辅助变量个数以及计算公式,在生成速度与周期长度两者之间进行权衡。

评分

参与人数 1鲜花 +2 收起 理由
qianyb + 2 学到一项新知识

查看全部评分

毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2010-2-27 13:25:18 | 显示全部楼层
原来如此,又学到一项新知识了,谢谢
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2010-2-27 13:36:42 | 显示全部楼层
晃动鼠标时,鼠标指针的坐标参数变化是一列性质良好的随机数。

这列随机数的产生速度比抛硬币、投骰子快多了

千万别用C++标准库里自带的rand()函数,这个rand()函数太挫了。

比如下面这段代码……#incl ...
KeyTo9_Fans 发表于 2010-2-27 13:21



原来winrar的压缩效果还与这个有关,以前只知道加密软件产生随机数的种子的时候需要不断晃动鼠标。看来即使是随机数,里面也有很大的学问呀
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2010-2-27 15:47:26 | 显示全部楼层
HugeCalc 的随机数算法部分参考了 Donald E.Knuth 的《计算机程序设计艺术》Vol.2
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
发表于 2010-2-28 15:25:15 | 显示全部楼层
# unsigned int s;        //辅助变量
#

# int rand16()        //生成一个0到15的随机数
# {
#         s=s*s+s/13+rand();
#         return s%16;
# }


这个办法确实很好啊。以前都没有这方面的思考
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
 楼主| 发表于 2010-2-28 15:33:04 | 显示全部楼层
弄了半天,我还是不知道郭的随机数的算法,其实随机数的生成在加密软件中是很重要的。我不知道郭使用什么算法,希望能给出一个有效链接。如果一个随机数很容易被猜到或者循环的周期很短,其实这种随机数的算法是很失败的。
毋因群疑而阻独见  毋任己意而废人言
毋私小惠而伤大体  毋借公论以快私情
您需要登录后才可以回帖 登录 | 欢迎注册

本版积分规则

小黑屋|手机版|数学研发网 ( 苏ICP备07505100号 )

GMT+8, 2024-11-21 20:44 , Processed in 0.033787 second(s), 17 queries .

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表