真/伪随机数发生器类

一直想要弄一个能够生成真随机数的类,但因未能找到合适的真随机因子而未能完成。前些天偶然了解到IA32的CPU具有一个时钟周期计数器,能够提供自CPU复位后至今累计的时钟周期数。忽然觉得这个正是最易得到而又最难预测的真随机因子。

  这里我们不讨论严格意义上的“真随机”数,以免陷入无尽的口水里。我认为由于系统运行状况的不确定性,实际上连总是以固定间隔获取时钟计数都很难做到。再加上多核处理器各核心的负载变化、睿频功能的状态变更、CPU流水线被中断的情况不同、CPU缓存的命中变化、操作系统的任务调度、真正随机的外界事件干扰(比如键盘/鼠标操作,网络通信变化等等)......如此多的变数影响下,我们获得的时钟计数完全无法预测。用它做真随机因子的随机数算法就已经是真正的随机数了。至少,对于日常的需求而言已经可以得到满足了。

  和通常使用的系统时间毫秒数相比较,这个时钟周期计数更为多变。系统时间一毫秒才改变一次,足够一个快速的随机数发生器产生超过十万个随机数了。因为期间系统时间没有改变,用它生成的随机数其实还是一个固定序列。而时钟计数则能保证每次调用都不相同,生成一个随机数的时间至少要经过几十个时钟周期了。使用它来生成随机数能保证不会出现固定序列的现象。

  另一个好处是运行效率很高。系统时间的获取需要调用操作系统API,费时费力。而时钟计数则仅需几条汇编命令就能取到,轻巧容易。

  网上曾有人直接把时钟周期计数的低位作为随机数来使用,但我认为这还是不妥。毕竟该数字重复一次的周期太长了点,在此期间用户获得的就是一个虽然间距随机但却一直在不断增大的数字序列,怎么看都不像是一个随机数。所以,我把他作为随机因子添加到线性同余法随机数发生器的算法里,使得到的数字序列成为真正无规律的真随机序列。

  这个算法的运行效率还是非常高的,不带参数时大约能在几纳秒的时间里生成一个真随机数。带上参数后63位算法的速度下降很多,大约需要15纳秒才能生成一个。原因是它需要做128位乘法运算来整理返回值。我最初用浮点数来做返回值整理,速度更快,但发现计算误差太可恶了:用n做参数本该生成0到n-1的数值,结果调试中改置极限参数后竟然在输出里看到了n。于是改用内联汇编来做整理运算。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章