看了半天还是不明白楼主心目中“真正的随机函数”应该是什么样的。
一般的高级语言都有自己内置的随机数发生器,这些发生器根据一个给定的种子以及特定
的算法产生“伪随机数列”,由于要满足效率和随机两方面的需求,随机数发生器的算法是
有讲究的(在一般情况下,即要“随机”,又要“可重现”,又不能太慢或者占用太多的存
储器资源),Delphi随机数发生器所采用的将位运算与MOD算子进行组合的算法就是非常经
典的一种。更加复杂的算法虽然在随机性方面会更加好(这是废话,越复杂的当然越显得
“随机”啦),但是所需要的时间和空间开销都会不可避免的增大,所以只在有特殊要求的
情况下由程序员自己编写。
在随机算法确定了以后,剩下的问题就是用来给随机数发生器的初始数据的来源了——由
于计算机运算的精确性和可再现性,即便是再复杂的算法,如果初始参数没有变化,那么无
论运行多少次,其结果(序列)都必然是相同的。有鉴于此,设置初始参数也就成了随机算
法中不可或缺的一环。由于程序运行的环境中绝大多数信息都不具备足够的随机性(比如机
器名、用户名、IP、Handle、内存地址等——它们都无法在多次调用时有足够的差别),为
了省事,Delphi的随机数发生器提供了一个利用系统时钟来初始化随机数种子的Ramdomize
过程——程序员也可以指定特定的数字赋予RandSeed全局变量来初始化随机数发生器。看看
Ramdomize的源码:
procedure Randomize;
var
Counter: Int64;
begin
if QueryPerformanceCounter(Counter) then
RandSeed := Counter
else
RandSeed := GetTickCount;
end;
——Delphi所做的就是利用高精度时钟(或者低精度的GetTickCount)来做为RandSeed罢
了。
现在可能存在的情况是:有使用随机数的程序中,从头到尾都没有Randomize过——其结
果就是每次运行都是“同样的随机”;有的程序则是在程序启动时进行一次性Randomize,
然后就没有再更改过种子;有的程序是在每次进入某个状态时进行初始化,而在该状态内没
有任何主动改变随机种子的动作(比如牌类游戏在每次发牌之前根据时钟初始化随机种子,
直到牌局结束,有的随机抽题考试也是这种模式)——其结果就是有可能被高手从已经得到
的伪随机序列反推出种子值从而预测之后的伪随机值(因为做为种子的时钟值的范围可以控
制在一个不大的范围内,然后利用相同算法的随机发生器进行穷举匹配)。
上面说了这么多,还是在普通的“可重现”随机数发生算法(即相同的初始值必然得到同
样的随机序列)的范畴内,如果楼主不需要可重现,那么可以利用定时器或者鼠标键盘事件
来做文章——每0.1秒或者MouseMove时都触发一次无用的Random调用,使得真正被用到的随
机数并不是“连续”获得的随机数,并且基本上不可能控制或者预测随机取数的间隔。
如果楼主需要更加“安全”的“非标准”随机数发生器(可重复的),网上有很多这类资
源,高抬贵手搜一下即可