再论随机数的发生算法 (50分)

  • 主题发起人 DarwinZhang
  • 开始时间
关于效率,我认为以上的算法都可以在一个较为固定的时间内获得一定的信息熵。
比如,我在 ID=1606150 中给出的代码,不确定性的产生速度大致为 6bit/ms,即这个算
法每秒可以产生6000个完全随机的二进制数。
容易看出,计时精度越高,单位时间内我们可以得到的信息熵就越大。我在上面的程序中
使用的是QueryPerformanceCounter API获得时间滴答数,我试验了一下,在我的机器上,
QueryPerformanceCounter每秒钟增大3579545,也就是可以精确到三百多万分之一秒。如果
我们进一步采用直接获得CPU的周期数的方法,还是以我的机器为例——CPU的主频为1533MHz
——即每秒增大1533000000,与QueryPerformanceCounter相比,精度提高428倍!如果说用
QueryPerformanceCounter每秒可以获得6000bit的不确定性,那么用RDTSC指令每秒中就可以
得到6000*(Lg428/Lg2)=52448个随机二进制数!——够用了吧:)
 
to creation-zy兄:
自从您提出用CPU周期标定后,我就使用它作为发生随机数字的办法了。
我的意思是,windows系统作一个动作,大约多少时间产生的随机性就基本稳定了,
因为执行时间达到一个限度之后,时间越长,随机性和总时间的商就会越小。
而进行随机数字的记录也是需要一定时间的。这样,就有一个选择动作时间长短的问题。
而且,这个时间应该还和不同的机器有关系,所以颇感头疼。
btw: 我用CPU周期来获得 QueryPerformanceCounter 的执行时间,结果发现并非随机。
应该是执行QueryPerformanceCounter时间过短的缘故。
 
to DarwinZhang兄:
我明白了,您的意思是:假如一个耗时约1ms的过程可以产生Nbit信息,如果我们将这个
过程从1ms延长到1000ms,可以获得的信息量极可能不是1000*Nbit,而可能是100*Nbit甚至
更少——因为在计算机系统中,对同一个过程来说,它产生的熵并不一定与该过程消耗的时
间长短成正比——与之相反,实际情况往往是这样的:如果我们以算法消耗的时间为x轴座
标,产生的信息熵为y轴座标,根据实验的数据进行描点——我估计其结果应该与自控中的
阶越函数响应曲线(方程为: y=a*(1-e^(-x*b)),(a,b>0,x>=0))类似:是一条越往后越
平滑、无限接近某个上限的光滑曲线。对曲线上的点来说,越靠近x轴的原点,图像上的点
与原点的连线的斜率就越大——而这个斜率就是该算法在该时间内的信息熵产生速度!不难
看出,为了获得尽可能大的速度,产生信息熵的过程消耗的时间就应该尽可能的短。我认为
在Windows系统中,1ms还是可以接受的——因为更短的时间只能依靠函数调用来实现——而
这种方法的随机性不是很好。
综上所述,我的观点是——用于直接获得随机信息的过程时间应该尽可能的短(毫秒级),
又由于单个过程产生的熵很有限,如果要一次获得足够多的熵(比如64bit),我们完全可
以用函数调用多次随机过程,进行累积。
 
本来结了,现在看来也受到影响了。就不重复了。
 
good news:
我查到,如果任意I/O动作结束,Windows将会微调线程的优先级别,
这意味这任意使用一个足够长的延迟程序,
都将产生一个真正的不可预料的随机性,
证明上面的讨论完全有效!!![:)]
 
晕倒!我发现在单位的机器上Sleep过程的耗时稳定在15.3ms的整数倍...为了提高产生效
率,只好改成API调用。
详细的源代码见 http://www24.brinkster.com/creationzy/prg/src/RndGenSrc.zip
利用API调用耗时的不确定性生成随机数,在PIV 1.6A上每秒钟可以生成4096个杂凑之后
的随机数(缺省情况下每产生一个32Bit的随机数需要调用8次随机过程)。
 
creation-zy 兄: 那个地方下不了. : (
请将关键代码帖出来好吗?
 
//延时过程
procedure Delay(lMilliSeconds: Dword);
var
MyEvent :Thandle;
begin
MyEvent := CreateEvent(nil,True,False,nil) ;
waitforSingleObject(MyEvent,lMilliSeconds);
CloseHandle(MyEvent);
end;

//获得原始随机数
function GetOriginalRnd: Integer;
var
TimerHi,TimerLo:DWORD;
begin
asm
dw 310Fh // rdtsc
mov TimerLo, eax
mov TimerHi, edx
end;
//Sleep(1);
//Cost more than 15ms -- too long.
Delay(0);
with frmRnddo
Caption:=Caption;
Application.ProcessMessages;
asm
dw 310Fh // rdtsc
sub eax, TimerLo
sbb edx, TimerHi
mov TimerLo, eax
mov TimerHi, edx
end;
Result:=Integer(TimerLo-AverageValue);
end;

//获得一个随机数
function GetARndNumber(HashRnd:Boolean):Integer;
var
i,rnd,LastRnd:Integer;
begin
if HashRnd then
//散列随机数
begin
Result:=10101010;
LastRnd:=0;
for i:=EntropyTimesdo
wnto 1do
//多次调用随机过程,增大随机熵
begin
rnd:=GetOriginalRnd;
Result:=(Result shl 5) xor (HashInt(rnd)-Result) //HashInt和StrHash是自编的散列函数
+StrHash(IntToHex(rnd,8)+' '+IntToStr(HashInt(Result xor (LastRnd+753214897))));
LastRnd:=rnd;
end;
end
else
begin
rnd:=GetOriginalRnd;
Result:=(rnd shr 2) or (rnd and Integer($C0000000));
end;
end;
 
火龙真的,听过测不准关系没有?
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
I
回复
0
查看
737
import
I
顶部