这是一个理论问题;作为计算机科学爱好者,我已经想到了这一点,并试图了解可能(或正在)用于解决此问题的逻辑和方法。
问题:假设您有一些数字空间可以漫游以获取某种ID值。您需要在该空间内生成RANDOM号码。
要求:
我曾考虑过四种方法来生成这些庞大的唯一数字集:
当然,在没有考虑实际用例的情况下,我没有“最佳”选择。我对这种问题带给我的思想和逻辑实验更感兴趣,并想知道是否有人使用了其他技术,或者至少想到了其他方法来解决这样的问题。在包含视频ID的YouTube中,您确实看到了至少与之类似的东西。当然,谷歌是可以在不到一秒钟的时间内为您“搜索互联网”的公司,因此,他们的方法可能不适用于“其他任何人”。
答案 0 :(得分:2)
这是理论上的答案。
由于在此数字空间内永远不会重复生成任何数字,因此该算法有效地生成了数字空间的 some 排列。这暗示它应该选择一个特定的排列并顺序生成。
如果空间大小为N
,则可能有N!
个排列。给定置换索引,generate it一次很容易,一个元素。随机选择一个排列并生成它。
选定的排列可能是一个标识(产生ID的0, 1, 2, ...
序列)。它看起来不是很随机,但攻击者仍然无法预测它。
答案 1 :(得分:1)
我想您事先知道要多少个随机数。
我建议对Bloom filter使用可扩展方法来优化查询。请注意,Bloom过滤器不存储实际值,并且有可能认为它看到了没有的值。在这种情况下,这也不是一个重大损害,并且几乎不可能预测哪些数字将被错误地指控为没有被发现。
您可以调整过滤器的大小,以权衡内存和所需的随机数。调整大小,以使最终的误报率是10%,比起误报率是1%,生成数字的速度变慢,但占用的内存更少。对于非常大的数据集,可以很容易地并行处理Bloom过滤器,以使其在多台计算机上运行。对于要快速生成的非常大的数据集,您甚至可以使用两级哈希,其中顶级确定将检查哪些哈希函数子集,第二个哈希针对保存的数据运行。这种设计使您可以在机器之间并行执行两项检查,并首先进行负载平衡。这样会产生疯狂的吞吐量。
一个重要的缺点是您必须预先确定最终的随机数池有多大。因为一旦过滤器被过多的数据阻塞,您就无法轻易调整其大小。
答案 2 :(得分:1)
一种众所周知的算法是在数字空间中使用一些值序列-例如,对于2的幂范围,可以使用线性同余序列-然后对值进行加密。由于加密功能必须是同构的,否则将无法进行准确的解密,因此该重复操作会一直进行到基本序列结束为止。
当然,您将要保护您的加密密钥以及用于基础序列的任何参数,并且很难维护这些机密。但是输出值肯定看起来是随机的。您将不得不在可能的安全问题与实际问题域的需求之间取得平衡。
某些循环生成器可以在O(1)中提前k
代。如果选择其中之一,则可以通过为每个并行进程分配适当的种子来并行化“随机”数生成。如果某个进程通过其所有k
的值运行,它只会向主服务器请求新的范围分配,或者它本身是否可以访问持久性存储。
答案 3 :(得分:0)
使用可扩展的方法,除了占用内存之外,提取的速度也变慢了。但是,假设有N个数字的空间(如果用一维数组表示),则要进行多个这样的空间的提取,我平均必须执行N / 2次迭代。但是如果此空间是一个方阵,例如,对于我提取的每个数字,平均而言,我将有Sqrt(N)/ 2 + Sqrt(N)/ 2次迭代,即行搜索和列搜索。对于3维矩阵,迭代次数甚至更少,或者N ^(1/3)/ 2 + N ^(1/3)/ 2 + N ^(1/3)/ 2,依此类推,增加与维数结构关联的维数空间,总的迭代次数总是较小。 显然,对于第一个维度以上的每个维度,我必须考虑向量空间紧随其后的维度中可用元素的数量。
例如,我报告了这个单元,它是在Delphi下以汇编器(受保护模式)编写的。要提取2 ^ 27个数字,在一台旧ACER TravelMate 4220笔记本电脑上的GetRndGRNum()函数需要37秒(我没有时间翻译英语注释):
unit x;
interface
Const GRMinCellValue=-1 ShL 31;
GRMaxDeltaNum=(1 ShL 27)-1;
Type {2} TGRData0=Record
{1} GRNumArrAmount0,
{1} GRNumArr0:Byte;
End;
{16} TGRArr1=Array [0..7] Of TGRData0;
{17} TGRData1=Record
{1} GRNumArrAmount1:Byte;
{16} GRNumArr1:TGRArr1;
End;
{136} TGRArr2=Array [0..7] Of TGRData1;
{137} TGRData2=Record
{1} GRNumArrAmount2:Byte;
{136} GRNumArr2:TGRArr2;
End;
{1096} TGRArr3=Array [0..7] Of TGRData2;
{1097} TGRData3=Record
{1} GRNumArrAmount3:Byte;
{1096} GRNumArr3:TGRArr3;
End;
{8776} TGRArr4=Array [0..7] Of TGRData3;
{8777} TGRData4=Record
{1} GRNumArrAmount4:Byte;
{8776} GRNumArr4:TGRArr4;
End;
{70216} TGRArr5=Array [0..7] Of TGRData4;
{70217} TGRData5=Record
{1} GRNumArrAmount5:Byte;
{70216} GRNumArr5:TGRArr5;
End;
{561736} TGRArr6=Array [0..7] Of TGRData5;
{561737} TGRData6=Record
{1} GRNumArrAmount6:Byte;
{561736} GRNumArr6:TGRArr6;
End;
{4493896} TGRArr7=Array [0..7] Of TGRData6;
{4493897} TGRData7=Record
{1} GRNumArrAmount7:Byte;
{4493896} GRNumArr7:TGRArr7;
End;
{35951176} TGRArr8=Array [0..7] Of TGRData7;
{35951185} TGRData8=Record
{1} GRNumArrAmount8:Byte;
{4} GRNumMin8,
{4} GRNumMax8:Integer;
{35951176} GRNumArr8:TGRArr8;
End;
TGRData8Ptr=^TGRData8;
TRndXSeed=Array[0..3] Of Cardinal;
Var RndXSeed:TRndXSeed=(123456789, (* X: Seed *)
362436000, (* Y: Must be <>0 *)
521288629, (* Z: Must be <>0 *)
7654321); (* C: Must be <>0 *)
Function GetPtr (PValue:Integer):Pointer;
{Trasforma il valore PValue IN un PUNTATORE POINTER.
NOTE: È scritta IN ASSEMBLER.
Non chiama alcuna Sub-ROUTINE.
Testata con successo}
Function GetPtrValue (P:Pointer):Integer;
{Converte il PUNTATORE P IN un valore.
NOTE: È scritta IN ASSEMBLER.
Non chiama alcuna Sub-ROUTINE.
Testata con successo}
Procedure MyFillChar (M:Pointer;S,V:Cardinal);
{ Analoga alla System.FillChar(), ma più veloce.
NOTE: è scritta interam. IN ASSEMBLER.
Non effettua alcun salto (CALL, Jmp o salto condizionato),
ed è molto veloce.
Per impostare a 0 la VAR. A
(di tipo BYTE, WORD, SMALLINT o INTEGER):
MyFillChar(@A,SIZEOF(A),0);
Per impostare a 0 la VAR. A
(di tipo T=RECORD):
MyFillChar(@A,SIZEOF(A),0) }
Procedure ReSetGRConfig (GRConfig:TGRData8Ptr;
Min,Max:Integer);
(* (Re)inizializza l' estrazione di numeri casuali,
compresi tra Min e Max, con GetRndGRNum(GRConfig).
I valori ammessi per Min e Max
vanno da -2147483647 a +2147483647,
ma il numero massimo di numeri
che si possono estrarre è 134217728.
Se Min e Max costituiscono un range troppo ampio,
sarà ristretto il suddetto range e
sarà alzato il valore minimo.
è possibile specificare Min>Max *)
Function GetRndGRNum (GRConfig:TGRData8Ptr):Integer;
(* Estrae un numero casuale nel range Min-Max sempre
diverso da quelli estratti precedentemente.
Ritorna GRMinCellValue (-2147483648)
se non ci sono altri numeri da estrarre.
Inizializzare l' estrazione con ReSetGRConfig(GRConfig,Min,Max) *)
implementation
Uses Math;
Function GetPtr(PValue:Integer):Pointer; Assembler;
(* EAX EDX ECX are 1°, 2° AND 3° PARAMETERs.
Can freely modify the EAX, ECX, AND EDX REGISTERs. *)
Asm
Mov EAX,PValue
End;
Function GetPtrValue(P:Pointer):Integer; Assembler;
(* EAX EDX ECX are 1°, 2° AND 3° PARAMETERs.
Can freely modify the EAX, ECX, AND EDX REGISTERs. *)
Asm
Mov EAX,P
End;
Procedure MyFillChar(M:Pointer;S,V:Cardinal); Assembler;
(* EAX EDX ECX are 1°, 2° AND 3° PARAMETERs.
Can freely modify the EAX, ECX, AND EDX REGISTERs. *)
Asm
Push EDI
Mov EDI,M (* EAX *)
Mov EAX,V (* ECX *)
Mov ECX,S (* EDX *)
ClD
Mov AH,AL
Mov DX,AX
ShL EAX,16
Mov AX,DX
Mov EDX,ECX
ShR ECX,2
Rep StoSD
SetB CL
Rep StoSW
Test DL,1
SetNE CL
Rep StoSB
Pop EDI
End;
Procedure ReSetGRConfig(GRConfig:TGRData8Ptr;
Min,Max:Integer);
Var I0,I1,I2,I3,I4,I5,I6,I7,I8:Byte;
Diff,Amount,Filled:Integer;
Begin
Inc(Min,Integer(Min=GRMinCellValue));
Diff:=Max-Min+Integer(Max=GRMinCellValue);
Dec(Diff,Integer(Abs(Diff)>GRMaxDeltaNum)*
(Diff-Sign(Diff)*GRMaxDeltaNum));
Filled:=0;
If Assigned(GRConfig) Then
With GRConfig^ Do
Begin
GRNumMin8:=Max-Diff*Integer(Diff>=0);
Diff:=Abs(Diff);
GRNumMax8:=GRNumMin8+Diff;
Amount:=Diff+1;
I8:=0;
Inc(Filled,9);
While (I8<8) And (Amount<>0) Do
With GRNumArr8[I8] Do
Begin
I7:=0;
Inc(Filled);
While (I7<8) And (Amount<>0) Do
With GRNumArr7[I7] Do
Begin
I6:=0;
Inc(Filled);
While (I6<8) And (Amount<>0) Do
With GRNumArr6[I6] Do
Begin
I5:=0;
Inc(Filled);
While (I5<8) And (Amount<>0) Do
With GRNumArr5[I5] Do
Begin
I4:=0;
Inc(Filled);
While (I4<8) And (Amount<>0) Do
With GRNumArr4[I4] Do
Begin
I3:=0;
Inc(Filled);
While (I3<8) And (Amount<>0) Do
With GRNumArr3[I3] Do
Begin
I2:=0;
Inc(Filled);
While (I2<8) And (Amount<>0) Do
With GRNumArr2[I2] Do
Begin
I1:=0;
Inc(Filled);
While (I1<8) And (Amount<>0) Do
With GRNumArr1[I1] Do
Begin
I0:=Integer((8+Amount-Abs(8-Amount)) ShR 1);
GRNumArrAmount0:=I0;
GRNumArr0:=0;
Dec(Amount,I0);
Inc(Filled,2);
Inc(I1);
End;
GRNumArrAmount1:=I1;
Inc(I2);
End;
GRNumArrAmount2:=I2;
Inc(I3);
End;
GRNumArrAmount3:=I3;
Inc(I4);
End;
GRNumArrAmount4:=I4;
Inc(I5);
End;
GRNumArrAmount5:=I5;
Inc(I6);
End;
GRNumArrAmount6:=I6;
Inc(I7);
End;
GRNumArrAmount7:=I7;
Inc(I8);
End;
GRNumArrAmount8:=I8;
(* 108'000'000= $66ff300
I6=7, I5=7, I4=16, I3=16, I2=3, I1=16, I0=16 = $7700300 *)
MyFillChar(GetPtr(GetPtrValue(GRConfig)+Filled),
SizeOf(GRConfig^)-Filled,0);
End;
End;
Function GetRndGRNum(GRConfig:TGRData8Ptr):Integer; Assembler;
{ EAX EDX ECX are 1°, 2° AND 3° PARAMETERs.
Can freely modify the EAX, ECX, AND EDX REGISTERs. }
Var Am7P { Salvat. OFFSET(TGRData5.GRNumArrAmount7) dell' elem. trovato },
Am6P { Salvat. OFFSET(TGRData5.GRNumArrAmount6) dell' elem. trovato },
Am5P { Salvat. OFFSET(TGRData5.GRNumArrAmount5) dell' elem. trovato },
Am4P { Salvat. OFFSET(TGRData4.GRNumArrAmount4) dell' elem. trovato },
Am3P { Salvat. OFFSET(TGRData3.GRNumArrAmount3) dell' elem. trovato },
Am2P { Salvat. OFFSET(TGRData2.GRNumArrAmount2) dell' elem. trovato },
Am1P { Salvat. OFFSET(TGRData1.GRNumArrAmount1) dell' elem. trovato },
GRData8Ptr { Salvataggio di GRConfig } :Integer;
RndN0 { Salvataggio num. casuale gener. dalla funzione RanInt() },
RndN1 { Salvataggio num. casuale gener. dalla funzione RanInt() },
RndN2 { Salvataggio num. casuale gener. dalla funzione RanInt() },
RndN3 { Salvataggio num. casuale gener. dalla funzione RanInt() },
RndN4 { Salvataggio num. casuale gener. dalla funzione RanInt() },
RndN5 { Salvataggio num. casuale gener. dalla funzione RanInt() },
RndN6 { Salvataggio num. casuale gener. dalla funzione RanInt() },
RndN7 { Salvataggio num. casuale gener. dalla funzione RanInt() },
RndN8 { Salvataggio num. casuale gener. dalla funzione RanInt() },
RC7 { Salvataggio pos. ("Real Counter") rec.TGRData7 trovato },
RC6 { Salvataggio pos. ("Real Counter") rec.TGRData6 trovato },
RC5 { Salvataggio pos. ("Real Counter") rec.TGRData5 trovato },
RC4 { Salvataggio pos. ("Real Counter") rec.TGRData4 trovato },
RC3 { Salvataggio pos. ("Real Counter") rec.TGRData3 trovato },
RC2 { Salvataggio pos. ("Real Counter") rec.TGRData2 trovato },
RC1 { Salvataggio pos. ("Real Counter") rec.TGRData1 trovato },
RC0 { Salvataggio pos. ("Real Counter") rec.TGRData0 trovato } :Byte;
Asm
Push EDI { Salva il registro EDI sullo STACK }
(* ---------------------------------------- *)
Mov EDI,GRConfig { Carica GRConfig (EAX) nel reg. EDI }
Mov EAX,GRMinCellValue { Carica il reg. di output con GRMinCellValue }
Or EDI,EDI { Se GRConfig=Nil ... }
JE @@00 { ... Ha finito, esce }
Cmp Byte Ptr [EDI],0 { Se GRConfig^.GRNumArrAmount6=0 ... }
JE @@00 { ... Ha finito, esce }
Mov GRData8Ptr,EDI { Salva GRConfig su GRData8Ptr }
(* ======================================== *)
LEA EDI,RndXSeed { Carica in EDI l' offs. di MyStrUt.MyRndXSeed }
(* ---------------------------------------- *)
(* - Generaz. di un num. casuale a 32 Bit - *)
(* ---------------------------------------- *)
Mov EAX,[EDI]
Mov EDX,69069
Mul EDX
Add EAX,12345
Mov [EDI],EAX // RndXSeed[0]:=69069*RndXSeed[0]+12345;
Mov EAX,[EDI+4]
ShL EAX,13
XOr [EDI+4],EAX // RndXSeed[1]:=RndXSeed[1] XOr (RndXSeed[1] ShL 13);
Mov EAX,[EDI+4]
ShR EAX,17
XOr [EDI+4],EAX // RndXSeed[1]:=RndXSeed[1] XOr (RndXSeed[1] ShR 17);
Mov EAX,[EDI+4]
ShL EAX,5
XOr [EDI+4],EAX // RndXSeed[1]:=RndXSeed[1] XOr (RndXSeed[1] ShL 5);
Mov EAX,[EDI+8]
Mov EDX,698769069
Mul EDX
Add EAX,[EDI+12]
AdC EDX,0 // EDX:EAX:=698769069*RndXSeed[2]+RndXSeed[3];
Mov [EDI+12],EDX // RndXSeed[3]:=T ShR 32;
Cmp EAX,[EDI+8]
Mov EAX,0
SetE AL
Or EDX,EDX
SetE DL
And AL,DL // EAX:=Cardinal(RndXSeed[2]=T)
Add EAX,[EDI]
Add EAX,[EDI+4] // RndX:=RndXSeed[0]+RndXSeed[1]+Cardinal(RndXSeed[2]=T);
(* ---------------------------------------- *)
(* - Fine generazione numero casuale ------ *)
(* ---------------------------------------- *)
Mov DL,AL { Carica i 7 Bit meno significat ... }
And DL,127 { ... del numero casuale generato ... }
Mov RndN0,DL { ... in RndN0 }
ShR EAX,7 { ... }
Mov DL,AL { Carica i 7 Bit meno significat ... }
And DL,127 { ... del numero casuale generato ... }
Mov RndN1,DL { ... in RndN1 }
ShR EAX,7 { ... }
Mov DL,AL { Carica i 7 Bit meno significat ... }
And DL,127 { ... del numero casuale generato ... }
Mov RndN2,DL { ... in RndN2 }
ShR EAX,7 { ... }
Mov DL,AL { Carica i 7 Bit meno significat ... }
And DL,127 { ... del numero casuale generato ... }
Mov RndN3,DL { ... in RndN3 }
ShR EAX,7 { ... }
Mov RndN4,AL { ... }
(* ---------------------------------------- *)
(* - Generaz. di un num. casuale a 32 Bit - *)
(* ---------------------------------------- *)
Mov EAX,[EDI]
Mov EDX,69069
Mul EDX
Add EAX,12345
Mov [EDI],EAX // RndXSeed[0]:=69069*RndXSeed[0]+12345;
Mov EAX,[EDI+4]
ShL EAX,13
XOr [EDI+4],EAX // RndXSeed[1]:=RndXSeed[1] XOr (RndXSeed[1] ShL 13);
Mov EAX,[EDI+4]
ShR EAX,17
XOr [EDI+4],EAX // RndXSeed[1]:=RndXSeed[1] XOr (RndXSeed[1] ShR 17);
Mov EAX,[EDI+4]
ShL EAX,5
XOr [EDI+4],EAX // RndXSeed[1]:=RndXSeed[1] XOr (RndXSeed[1] ShL 5);
Mov EAX,[EDI+8]
Mov EDX,698769069
Mul EDX
Add EAX,[EDI+12]
AdC EDX,0 // EDX:EAX:=698769069*RndXSeed[2]+RndXSeed[3];
Mov [EDI+12],EDX // RndXSeed[3]:=T ShR 32;
Cmp EAX,[EDI+8]
Mov EAX,0
SetE AL
Or EDX,EDX
SetE DL
And AL,DL // EAX:=Cardinal(RndXSeed[2]=T)
Add EAX,[EDI]
Add EAX,[EDI+4] // RndX:=RndXSeed[0]+RndXSeed[1]+Cardinal(RndXSeed[2]=T);
(* ---------------------------------------- *)
(* - Fine generazione numero casuale ------ *)
(* ---------------------------------------- *)
Mov DL,AL { ... }
And DL,7 { ... }
ShL DL,4 { ... }
Or RndN4,DL { ... }
ShR EAX,3 { ... }
Mov DL,AL { Carica i 7 Bit meno significat ... }
And DL,127 { ... del numero casuale generato ... }
Mov RndN5,DL { ... in RndN5 }
ShR EAX,7 { ... }
Mov DL,AL { Carica i 7 Bit meno significat ... }
And DL,127 { ... del numero casuale generato ... }
Mov RndN6,DL { ... in RndN6 }
ShR EAX,7 { ... }
Mov DL,AL { Carica i 7 Bit meno significat ... }
And DL,127 { ... del numero casuale generato ... }
Mov RndN7,DL { ... in RndN7 }
ShR EAX,7 { ... }
And AL,127 { ... }
Mov RndN8,AL { ... }
Mov EDI,GRData8Ptr { Carica GRConfig in EDI }
(* ======================================== *)
(* = Ricerca del record TGRData7 ========= *)
(* ======================================== *)
Mov AH,[EDI] { AH <- GRConfig^.GRNumArrAmount6 (amount) }
{in:127=out:amount-1
out<-in*amount/128}
Mul AH { AX <- in*amount }
ShR AX,7 { AL <- in*amount/128 }
Inc AL { AL <- in*amount/128+1 }
(* ---------------------------------------- *)
{EDI: GRNumArr8[CL].
AL: VC.
CL: RC.
CH: Temp=0}
Mov CX,255 { RC <- -1; Temp <- 0}
Add EDI,OFFSET TGRData8.GRNumArr8-TYPE(TGRData7) { EDI <- OFFSET ... }
{ ... GRConfig^.GRNumArr8-SizeOf(TGRData7) }
(* ---------------------------------------- *)
@@L8:Add EDI,TYPE(TGRData7) { EDI += SizeOf(TGRData7) }
Inc CL { RC += 1 }
Cmp Byte Ptr [EDI],1 { Se GRNumArr8[CL].GRNumArrAmount7<>0, ... }
CmC { ... }
SbB AL,CH { ... VC -= 1 }
JNE @@L8 { Se VC<>0, ripete il ciclo }
(* ---------------------------------------- *)
Mov Am7P,EDI { Salva OFFS(GRNumArr8[CL].GRNumArrAmount7) ...}
{ ... (EDI) in Am7P }
Mov RC7,CL { Salva RC (CL) in RC7 }
(* ======================================== *)
(* = Ricerca del record TGRData6 ========= *)
(* ======================================== *)
Mov AL,RndN7 { ... }
(* ---------------------------------------- *)
Mov AH,[EDI] { AH <- GRConfig^.GRNumArrAmount6 (amount) }
{in:127=out:amount-1
out<-in*amount/128}
Mul AH { AX <- in*amount }
ShR AX,7 { AL <- in*amount/128 }
Inc AL { AL <- in*amount/128+1 }
(* ---------------------------------------- *)
{EDI: GRNumArr7[CL].
AL: VC.
CL: RC.
CH: Temp=0}
Mov CX,255 { RC <- -1; Temp <- 0}
Add EDI,OFFSET TGRData7.GRNumArr7-TYPE(TGRData6) { EDI <- OFFSET ... }
{ ... GRConfig^.GRNumArr7-SizeOf(TGRData6) }
(* ---------------------------------------- *)
@@L7:Add EDI,TYPE(TGRData6) { EDI += SizeOf(TGRData6) }
Inc CL { RC += 1 }
Cmp Byte Ptr [EDI],1 { Se GRNumArr7[CL].GRNumArrAmount6<>0, ... }
CmC { ... }
SbB AL,CH { ... VC -= 1 }
JNE @@L7 { Se VC<>0, ripete il ciclo }
(* ---------------------------------------- *)
Mov Am6P,EDI { Salva OFFS(GRNumArr7[CL].GRNumArrAmount6) ...}
{ ... (EDI) in Am6P }
Mov RC6,CL { Salva RC (CL) in RC6 }
(* ======================================== *)
(* = Ricerca del record TGRData5 ========= *)
(* ======================================== *)
Mov AL,RndN6 { ... }
(* ---------------------------------------- *)
Mov AH,[EDI] { AH <- GRConfig^.GRNumArrAmount6 (amount) }
{in:127=out:amount-1
out<-in*amount/128}
Mul AH { AX <- in*amount }
ShR AX,7 { AL <- in*amount/128 }
Inc AL { AL <- in*amount/128+1 }
(* ---------------------------------------- *)
{EDI: GRNumArr6[CL].
AL: VC.
CL: RC.
CH: Temp=0}
Mov CX,255 { RC <- -1; Temp <- 0}
Add EDI,OFFSET TGRData6.GRNumArr6-TYPE(TGRData5) { EDI <- OFFSET ... }
{ ... GRConfig^.GRNumArr6-SizeOf(TGRData5) }
(* ---------------------------------------- *)
@@L6:Add EDI,TYPE(TGRData5) { EDI += SizeOf(TGRData5) }
Inc CL { RC += 1 }
Cmp Byte Ptr [EDI],1 { Se GRNumArr6[CL].GRNumArrAmount5<>0, ... }
CmC { ... }
SbB AL,CH { ... VC -= 1 }
JNE @@L6 { Se VC<>0, ripete il ciclo }
(* ---------------------------------------- *)
Mov Am5P,EDI { Salva OFFS(GRNumArr6[CL].GRNumArrAmount5) ...}
{ ... (EDI) in Am5P }
Mov RC5,CL { Salva RC (CL) in RC5 }
(* ======================================== *)
(* = Ricerca del record TGRData4 ========= *)
(* ======================================== *)
Mov AL,RndN5 { ... }
(* ---------------------------------------- *)
Mov AH,[EDI] { AH <- GRConfig^.GRNumArrAmount6 (amount) }
{in:127=out:amount-1
out<-in*amount/128}
Mul AH { AX <- in*amount }
ShR AX,7 { AL <- in*amount/128 }
Inc AL { AL <- in*amount/128+1 }
(* ---------------------------------------- *)
{EDI: GRNumArr5[CL].
AL: VC.
CL: RC.
CH: Temp=0}
Mov CX,255 { RC <- -1; Temp <- 0}
Add EDI,OFFSET TGRData5.GRNumArr5-TYPE(TGRData4) { EDI <- OFFSET ... }
{ ... TGRData5.GRNumArr5-SizeOf(TGRData4) }
(* ---------------------------------------- *)
@@L5:Add EDI,TYPE(TGRData4) { EDI += SizeOf(TGRData4) }
Inc CL { RC += 1 }
Cmp Byte Ptr [EDI],1 { Se GRNumArr5[CL].GRNumArrAmount4<>0, ... }
CmC { ... }
SbB AL,CH { ... VC -= 1 }
JNE @@L5 { Se VC<>0, ripete il ciclo }
(* ---------------------------------------- *)
Mov Am4P,EDI { Salva OFFS(GRNumArr5[CL].GRNumArrAmount4) ...}
{ ... (EDI) in Am4P }
Mov RC4,CL { Salva RC (CL) in RC4 }
(* ======================================== *)
(* = Ricerca del record TGRData3 ========= *)
(* ======================================== *)
Mov AL,RndN4 { ... }
(* ---------------------------------------- *)
Mov AH,[EDI] { AH <- GRConfig^.GRNumArrAmount6 (amount) }
{in:127=out:amount-1
out<-in*amount/128}
Mul AH { AX <- in*amount }
ShR AX,7 { AL <- in*amount/128 }
Inc AL { AL <- in*amount/128+1 }
(* ---------------------------------------- *)
{EDI: GRNumArr4[CL].
AL: VC.
CL: RC.
CH: Temp=0}
Mov CX,255 { RC <- -1; Temp <- 0}
Add EDI,OFFSET TGRData4.GRNumArr4-TYPE(TGRData3) { EDI <- OFFSET ... }
{ ... TGRData4.GRNumArr4-SizeOf(TGRData3) }
(* ---------------------------------------- *)
@@L4:Add EDI,TYPE(TGRData3) { EDI += SizeOf(TGRData3) }
Inc CL { RC += 1 }
Cmp Byte Ptr [EDI],1 { Se GRNumArr4[CL].GRNumArrAmount3<>0, ... }
CmC { ... }
SbB AL,CH { ... VC -= 1 }
JNE @@L4 { Se VC<>0, ripete il ciclo }
(* ---------------------------------------- *)
Mov Am3P,EDI { Salva OFFS(GRNumArr4[CL].GRNumArrAmount3) ...}
{ ... (EDI) in Am3P }
Mov RC3,CL { Salva RC (CL) in RC3 }
(* ======================================== *)
(* = Ricerca del record TGRData2 ========= *)
(* ======================================== *)
Mov AL,RndN3 { ... }
(* ---------------------------------------- *)
Mov AH,[EDI] { AH <- GRConfig^.GRNumArrAmount6 (amount) }
{in:127=out:amount-1
out<-in*amount/128}
Mul AH { AX <- in*amount }
ShR AX,7 { AL <- in*amount/128 }
Inc AL { AL <- in*amount/128+1 }
(* ---------------------------------------- *)
{EDI: GRNumArr3[CL].
AL: VC.
CL: RC.
CH: Temp=0}
Mov CX,255 { RC <- -1; Temp <- 0}
Add EDI,OFFSET TGRData3.GRNumArr3-TYPE(TGRData2) { EDI <- OFFSET ... }
{ ... TGRData3.GRNumArr3-SizeOf(TGRData2) }
(* ---------------------------------------- *)
@@L3:Add EDI,TYPE(TGRData2) { EDI += SizeOf(TGRData2) }
Inc CL { RC += 1 }
Cmp Byte Ptr [EDI],1 { Se GRNumArr3[CL].GRNumArrAmount2<>0, ... }
CmC { ... }
SbB AL,CH { ... VC -= 1 }
JNE @@L3 { Se VC<>0, ripete il ciclo }
(* ---------------------------------------- *)
Mov Am2P,EDI { Salva OFFS(GRNumArr3[CL].GRNumArrAmount2) ...}
{ ... (EDI) in Am2P }
Mov RC2,CL { Salva RC (CL) in RC2 }
(* ======================================== *)
(* = Ricerca del record TGRData1 ========= *)
(* ======================================== *)
Mov AL,RndN2 { ... }
(* ---------------------------------------- *)
Mov AH,[EDI] { AH <- GRConfig^.GRNumArrAmount6 (amount) }
{in:127=out:amount-1
out<-in*amount/128}
Mul AH { AX <- in*amount }
ShR AX,7 { AL <- in*amount/128 }
Inc AL { AL <- in*amount/128+1 }
(* ---------------------------------------- *)
{EDI: GRNumArr2[CL].
AL: VC.
CL: RC.
CH: Temp=0}
Mov CX,255 { RC <- -1; Temp <- 0}
Add EDI,OFFSET TGRData2.GRNumArr2-TYPE(TGRData1) { EDI <- OFFSET ... }
{ ... TGRData2.GRNumArr2-SizeOf(TGRData1) }
(* ---------------------------------------- *)
@@L2:Add EDI,TYPE(TGRData1) { EDI += SizeOf(TGRData1) }
Inc CL { RC += 1 }
Cmp Byte Ptr [EDI],1 { Se GRNumArr2[CL].GRNumArrAmount1<>0, ... }
CmC { ... }
SbB AL,CH { ... VC -= 1 }
JNE @@L2 { Se VC<>0, ripete il ciclo }
(* ---------------------------------------- *)
Mov Am1P,EDI { Salva OFFS(GRNumArr2[CL].GRNumArrAmount1) ...}
{ ... (EDI) in Am1P }
Mov RC1,CL { Salva RC (CL) in RC1 }
(* ======================================== *)
(* = Ricerca del record TGRData0 ========= *)
(* ======================================== *)
Mov AL,RndN1 { ... }
(* ---------------------------------------- *)
Mov AH,[EDI] { AH <- GRConfig^.GRNumArrAmount6 (amount) }
{in:127=out:amount-1
out<-in*amount/128}
Mul AH { AX <- in*amount }
ShR AX,7 { AL <- in*amount/128 }
Inc AL { AL <- in*amount/128+1 }
(* ---------------------------------------- *)
{EDI: GRNumArr1[CL].
AL: VC.
CL: RC.
CH: Temp=0}
Mov CX,255 { RC <- -1; Temp <- 0}
Add EDI,OFFSET TGRData1.GRNumArr1-TYPE(TGRData0) { EDI <- OFFSET ... }
{ ... TGRData1.GRNumArr1-SizeOf(TGRData0) }
(* ---------------------------------------- *)
@@L1:Add EDI,TYPE(TGRData0) { EDI += SizeOf(TGRData0) }
Inc CL { RC += 1 }
Cmp Byte Ptr [EDI],1 { Se GRNumArr1[CL].GRNumArrAmount0<>0, ... }
CmC { ... }
SbB AL,CH { ... VC -= 1 }
JNE @@L1 { Se VC<>0, ripete il ciclo }
(* ---------------------------------------- *)
Mov RC0,CL { Salva RC (CL) in RC0 }
(* ======================================== *)
(* = Ricerca del Bit selezionato ========= *)
(* ======================================== *)
Mov AL,RndN0 { ... }
(* ---------------------------------------- *)
Mov AH,[EDI] { AH <- GRConfig^.GRNumArrAmount6 (amount) }
{in:127=out:amount-1
out<-in*amount/128}
Mul AH { AX <- in*amount }
ShR AX,7 { AL <- in*amount/128 }
Inc AL { AL <- in*amount/128+1 }
(* ---------------------------------------- *)
{ DX: GRNumArr0.
AL: VC.
CL: RC.
CH: Temp=0}
Mov CX,255 { RC <- -1; Temp <- 0}
Mov DL,[EDI+OFFSET TGRData0.GRNumArr0] { DL <- TGRData0.GRNumArr0 }
(* ---------------------------------------- *)
@@L0:Inc CL { RC += 1 }
ShR DL,1 { GRNumArr0>>1 }
CmC { Se FCarry=0 ... }
SbB AL,CH { ... VC -= 1 }
JNE @@L0 { Se VC<>0, ripete il ciclo }
(* ======================================== *)
Mov DL,1 { ... }
ShL DL,CL { ... DL <- 1<<RC }
Or [EDI+OFFSET TGRData0.GRNumArr0],DL { Marca il num. come già estratto}
(* ---------------------------------------- *)
Mov EDX,GRData8Ptr { Carica GRConfig in EDX }
Dec Byte Ptr [EDI] { TGRData0.GRNumArrAmount0 -= 1 }
JNE @@01 { Se TGRData0.GRNumArrAmount0<>0, salta }
Mov EDI,Am1P { Carica OFFS(TGRData1.GRNumArrAmount1) in EDI }
Dec Byte Ptr [EDI] { TGRData1.GRNumArrAmount1 -= 1 }
JNE @@01 { Se TGRData1.GRNumArrAmount1<>0, salta }
Mov EDI,Am2P { Carica OFFS(TGRData2.GRNumArrAmount2) in EDI }
Dec Byte Ptr [EDI] { TGRData2.GRNumArrAmount2 -= 1 }
JNE @@01 { Se TGRData2.GRNumArrAmount2<>0, salta }
Mov EDI,Am3P { Carica OFFS(TGRData3.GRNumArrAmount3) in EDI }
Dec Byte Ptr [EDI] { TGRData3.GRNumArrAmount3 -= 1 }
JNE @@01 { Se TGRData3.GRNumArrAmount3<>0, salta }
Mov EDI,Am4P { Carica OFFS(TGRData4.GRNumArrAmount4) in EDI }
Dec Byte Ptr [EDI] { TGRData4.GRNumArrAmount4 -= 1 }
JNE @@01 { Se TGRData4.GRNumArrAmount4<>0, salta }
Mov EDI,Am5P { Carica OFFS(TGRData5.GRNumArrAmount5) in EDI }
Dec Byte Ptr [EDI] { TGRData5.GRNumArrAmount5 -= 1 }
JNE @@01 { Se TGRData5.GRNumArrAmount5<>0, salta }
Mov EDI,Am6P { Carica OFFS(TGRData6.GRNumArrAmount6) in EDI }
Dec Byte Ptr [EDI] { TGRData6.GRNumArrAmount6 -= 1 }
JNE @@01 { Se TGRData6.GRNumArrAmount6<>0, salta }
Mov EDI,Am7P { Carica OFFS(TGRData7.GRNumArrAmount7) in EDI }
Dec Byte Ptr [EDI] { TGRData7.GRNumArrAmount7 -= 1 }
JNE @@01 { Se TGRData7.GRNumArrAmount7<>0, salta }
Dec Byte Ptr [EDX] { GRConfig^.GRNumArrAmount8 -= 1 }
(* ---------------------------------------- *)
@@01:MovZX EAX,RC7 { EAX <- pos. ("Real Count.") r. TGRData7 trov.}
ShL Al,3 { EAX <<= 3 }
Or AL,RC6 { EAX |= pos. ("Real Count.") r. TGRData6 trov.}
ShL AX,3 { EAX <<= 3 }
Or AL,RC5 { EAX |= pos. ("Real Count.") r. TGRData5 trov.}
ShL AX,3 { EAX <<= 3 }
Or AL,RC4 { EAX |= pos. ("Real Count.") r. TGRData4 trov.}
ShL AX,3 { EAX <<= 3 }
Or AL,RC3 { EAX |= pos. ("Real Count.") r. TGRData3 trov.}
ShL EAX,3 { EAX <<= 3 }
Or AL,RC2 { EAX |= pos. ("Real Count.") r. TGRData2 trov.}
ShL EAX,3 { EAX <<= 3 }
Or AL,RC1 { EAX |= pos. ("Real Count.") r. TGRData1 trov.}
ShL EAX,3 { EAX <<= 3 }
Or AL,RC0 { EAX |= pos. ("Real Count.") r. TGRData0 trov.}
ShL EAX,3 { EAX <<= 3 }
Or AL,CL { EAX |= pos. Bit selezionato }
(* ---------------------------------------- *)
Add EAX,[EDX+OFFSET TGRData8.GRNumMin8] { Somma GRConfig^.GRNumMin8 ... }
{ ... al numero cas. gen. }
(* ======================================== *)
@@00:Pop EDI { Ripristina il registro EDI dallo STACK }
End;
end.
答案 4 :(得分:0)
如果不必生成特定长度的数字,则可以生成unique random numbers,如下所示:
出于此答案的目的,唯一部分和随机部分的大小是任意的。出于大多数实际目的,唯一部分的长度至少应为64位,随机部分的长度至少应为128位。