Delphi BigInt Random无重复项
我将装置Delphi BigInt Random无重复项,delphi,biginteger,bigint,Delphi,Biginteger,Bigint,我将装置uBigIntsV4与组件TInteger 幸运的是,它有一个内置的random过程,让您选择一个非常高的随机数并将其作为字符串返回 但是我找不到一种方法来开发一个函数,它可以让我在不重复的情况下,从x到n绘制一个高随机数 由于本机无符号整数的范围覆盖所有情况,因此无法创建列表或数组 我怎样才能解决这个问题?很抱歉,我不熟悉uBigIntsV4。我希望它具有实现基本算术运算(*,+,mod)所需的所有功能。如果是这样,您可以使用以下公式计算下一个伪随机数 在a、c和m值上有三个限制 m
uBigIntsV4
与组件TInteger
幸运的是,它有一个内置的random
过程,让您选择一个非常高的随机数并将其作为字符串返回
但是我找不到一种方法来开发一个函数,它可以让我在不重复的情况下,从x
到n
绘制一个高随机数
由于本机无符号整数的范围覆盖所有情况,因此无法创建列表或数组
我怎样才能解决这个问题?很抱歉,我不熟悉uBigIntsV4。我希望它具有实现基本算术运算(*,+,mod)所需的所有功能。如果是这样,您可以使用以下公式计算下一个伪随机数 在a、c和m值上有三个限制
有关详细信息,请参见wiki。对不起,我不熟悉uBigIntsV4。我希望它具有实现基本算术运算(*,+,mod)所需的所有功能。如果是这样,您可以使用以下公式计算下一个伪随机数 在a、c和m值上有三个限制
有关详细信息,请参见wiki。我没有太多时间对我的答案发表评论,但是我创建的这个Delphi库将允许您在最小-最大范围内提取随机数,始终与以前提取的随机数不同,直到有更多随机数为止。 如果需要的话,稍后我可以进一步解释这个答案 注意:必须启用编译器优化选项;使用GetRndGVNum()可以提取范围大于65535的数字,只需增加常量DefGVNumArrSize(range=DefGVNumArrSize*8)
单位so;
{$A-}
{$B-}
{$U+}
{$W-}
接口
Const DefGVNumArrSize=8192;
MinCellValue=-1 ShL 31;
MaxDeltaNum=DefGVNumArrSize*8-1;
类型TGVNumArr=Byte的数组[0..DefGVNumArrSize-1];
TGVConfig=记录
{0}GvNum金额,
{4} GVNumArrMin:整数;
{8} GVNumArr:TGVNumArr;
结束;
Var MyRandSeed:Integer=0;
过程MyFillChar(M:指针;S,V:基数);
{与System.FillChar()类似,但速度更快。
注意:它完全是用汇编语言编写的。
不需要跳过(调用、JMP或条件跳转),
而且速度非常快。
将VAR设置为0.A
(类型为BYTE、WORD、SMALLINT或INTEGER):
MyFillChar(@A,SIZEOF(A),0);
将VAR设置为0.A
(T型=记录):
MyFillChar(@A,SIZEOF(A),0)}
函数CopyInt(IntIn:Integer;
IntPtrOut:指针):整数;
{使用IntIn e将布尔参数设置为IntPtrOut^
返回IntIn。
注意:它是用汇编语言编写的。
限制:无}
程序MyInitRand;
{初始化函数MyRandInt()的glob.VAR.MyRandSeed。
限制:无}
函数MyRandInt(最小值,最大值:整数):整数;
{返回一个介于最小值和最大值(包括最小值和最大值)之间的随机数。
限制:无。
注:允许最小值>最大值。
允许最小值和最大值具有32位符号的整数值。
使用Turbo PASCAL System.RandInt()的32位转换
程序ReSetGVConfig(变量GVConfig:TGVConfig;
最小值,最大值:整数);
(*(重新)初始化随机数的提取,
在最小值和最大值之间,使用GetRndGVNum(GVConfig)。
最小值和最大值允许的值
范围从-2147483647到+2147483647,
但是最大数量的数字
可以提取的是65536。
如果最小值和最大值的范围过宽,
上述范围e将受到限制
将提高最小值。
您可以指定最小值>最大值*)
函数GetRndGVNum(Var-GVConfig:TGVConfig):整数;
(*始终提取最小-最大范围内的随机数
与之前提取的不同。
返回到MinCellValue(-2147483648)
如果没有其他数字可提取。
使用ReSetGVConfig(GVConfig,最小值,最大值)*初始化提取
程序RndGVNum_试验(GVMin,GVMax:整数);
(*此库的测试程序*)
实施
使用数学、系统;
函数CopyInt(IntIn:Integer;IntPtrOut:Pointer):整数;汇编程序;
(*EAX EDX ECX为1°、2°和3°参数。
可以自由修改EAX、ECX和EDX寄存器*)
Asm
Mov EAX,IntIn
Mov[EDX],EAX
结束;
过程MyFillChar(M:指针;S,V:基数);汇编程序;
(*EAX EDX ECX为1°、2°和3°参数。
可以自由修改EAX、ECX和EDX寄存器。*)
Asm
推式电子数据交换
Mov EDI,M(*EAX*)
Mov EAX,V(*ECX*)
Mov ECX,S(*EDX*)
ClD
莫夫啊,艾尔
Mov-DX,AX
ShL EAX,16
Mov-AX,DX
Mov-EDX,ECX
ShR-ECX,2
雷普斯托德
挫折
代表StoSW
测试DL,1
塞特
代表StoSB
流行电子数据交换
结束;
程序MyInitRand;
开始
MyRandSeed:=整数(分数(时间)*4294967295);
结束;
函数NextRand:基数;汇编程序;
{EAX-EDX-ECX为1°、2°和3°参数。
可以自由修改EAX、ECX和EDX寄存器。}
Asm
推式电子数据交换
(* ---------------------------------------- *)
莉埃迪,米兰塞德
(* ---------------------------------------- *)
MovZX-EAX,单词Ptr[EDI]{RandSeed.w0}
Mov CX,8405H
Mul CX{New=Old.w0*8405H}
Mov CX[EDI]
Unit so;
{$A-}
{$B-}
{$U+}
{$W-}
interface
Const DefGVNumArrSize=8192;
MinCellValue=-1 ShL 31;
MaxDeltaNum=DefGVNumArrSize*8-1;
Type TGVNumArr=Array[0..DefGVNumArrSize-1] Of Byte;
TGVConfig=Record
{0} GVNumArrAmount,
{4} GVNumArrMin:Integer;
{8} GVNumArr:TGVNumArr;
End;
Var MyRandSeed:Integer=0;
Procedure MyFillChar (M:Pointer;S,V:Cardinal);
{ Similar to the System.FillChar (), but faster.
NOTE: it is written entirely IN ASSEMBLER.
Skip not required (CALL, JMP or conditional jump),
and it's very fast.
To set the VAR to 0. A
(of type BYTE, WORD, SMALLINT or INTEGER):
MyFillChar (@ A, SIZEOF (A), 0);
To set the VAR to 0. A
(type T = RECORD):
MyFillChar (@ A, SIZEOF (A), 0) }
Function CopyInt (IntIn:Integer;
IntPtrOut:Pointer):Integer;
{Set the BOOLEAN parameter to IntPtrOut ^ with IntIn e
returns IntIn.
NOTE: It is written IN ASSEMBLER.
RESTRICTIONS: None}
Procedure MyInitRand;
{Initialize the glob. VAR. MyRandSeed for the function MyRandInt ().
RESTRICTIONS: None}
Function MyRandInt (Min,Max:Integer):Integer;
{Returns a random number between MIN and MAX (inclusive).
RESTRICTIONS: None.
NOTES: Permitted MIN> MAX.
Allow integer values with 32-bit SIGN for MIN and MAX.
Use a 32-bit conversion of Turbo-PASCAL System.RandInt ()}
Procedure ReSetGVConfig (Var GVConfig:TGVConfig;
Min,Max:Integer);
(* (Re) initializes the extraction of random numbers,
between Min and Max, with GetRndGVNum (GVConfig).
The values allowed for Min and Max
range from -2147483647 to +2147483647,
but the maximum number of numbers
which can be extracted is 65536.
If Min and Max constitute a too wide range,
the aforementioned range e will be restricted
the minimum value will be raised.
you can specify Min> Max *)
Function GetRndGVNum (Var GVConfig:TGVConfig):Integer;
(* Extracts a random number in the Min-Max range at all times
different from those previously extracted.
Return to MinCellValue (-2147483648)
if there are no other numbers to extract.
Initialize the extraction with ReSetGVConfig (GVConfig, Min, Max) *)
Procedure RndGVNum_Test (GVMin,GVMax:Integer);
(* Test program of this library *)
implementation
Uses Math,SysUtils;
Function CopyInt(IntIn:Integer;IntPtrOut:Pointer):Integer; Assembler;
(* EAX EDX ECX are 1°, 2° AND 3° PARAMETERs.
Can freely modify the EAX, ECX, AND EDX REGISTERs *)
Asm
Mov EAX,IntIn
Mov [EDX],EAX
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 MyInitRand;
Begin
MyRandSeed:=Round(Frac(Time)*4294967295);
End;
Function NextRand:Cardinal; Assembler;
{ EAX EDX ECX are 1°, 2° AND 3° PARAMETERs.
Can freely modify the EAX, ECX, AND EDX REGISTERs. }
Asm
Push EDI
(* ---------------------------------------- *)
LEA EDI,MyRandSeed
(* ---------------------------------------- *)
MovZX EAX,Word Ptr [EDI] { RandSeed.w0 }
Mov CX,8405H
Mul CX { New = Old.w0 * 8405H }
Mov CX,[EDI]
ShL CX,3 { New.w2 += Old.w0 * 808H }
Add Ch,CL
Add DX,CX
Mov CX,[EDI+2]
Add DX,CX { New.w2 += Old.w2 * 8405H }
ShL CX,2
Add DX,CX
Add DH,CL
ShL CX,5
Add DH,CL
Add AX,1
AdC DX,0 { New += 1 }
ShL EDX,16
Or EAX,EDX { EDX= DX:AX }
Mov [EDI],EAX
(* ---------------------------------------- *)
Pop EDI
End;
Function MyRandInt(Min,Max:Integer):Integer; Assembler;
{ EAX EDX ECX are 1°, 2° AND 3° PARAMETERs.
Can freely modify the EAX, ECX, AND EDX REGISTERs. }
Asm
Push ESI
Push EDI
Mov ESI,Max {A}
Mov EDI,Min {B}
{$IFDEF Delphi_7_Plus}
Mov ECX,EDI
Cmp EDI,ESI
CMovGE EDI,ESI {MIN}
CMovGE ESI,ECX {MAX}
{$ELSE}
XOr ECX,ECX
Sub EDI,ESI
Mov EAX,EDI
SetGE CL
Dec ECX
And EDI,ECX
Add EDI,ESI
Not ECX
And EAX,ECX
Add ESI,EAX
{$ENDIF}
Sub ESI,EDI
Inc ESI {ESI= MAX-MIN+1}
Call NextRand {EAX= 32 Bit Random number}
Mul ESI {EDX:EAX= EAX*(MAX-MIN+1)}
Add EDX,EDI
Mov EAX,EDX {@RESULT= EAX*(MAX-MIN+1)/(65536*65536)+MIN}
Pop EDI
Pop ESI
End;
Procedure ReSetGVConfig(Var GVConfig:TGVConfig;
Min,Max:Integer);
Var Diff:Integer;
Begin
With GVConfig Do
Begin
Inc(Min,Integer(Min=MinCellValue));
Diff:=Max-Min+
Integer(Max=MinCellValue);
Dec(Diff,
Integer(Abs(Diff)>MaxDeltaNum)*
(Diff-Sign(Diff)*MaxDeltaNum));
GVNumArrAmount:=Abs(Diff)+1;
GVNumArrMin:=Max-Diff*Integer(Diff>=0);
MyFillChar(@GVNumArr,SizeOf(GVNumArr),0);
End;
End;
Function GetRndGVNum(Var GVConfig:TGVConfig):Integer; Assembler;
{ EAX EDX ECX are 1°, 2° AND 3° PARAMETERs.
Can freely modify the EAX, ECX, AND EDX REGISTERs. }
Asm
Push EBX
Push ESI
Push EDI
Mov EDI,GVConfig
Mov EAX,MinCellValue
Mov EDX,[EDI+OFFSET TGVConfig.GVNumArrAmount]
Or EDX,EDX
JE @@00
Mov EAX,1
Call MyRandInt
{EDI: GRConfig.GRNumArr[I].
EAX: VC.
EBX: I.
ECX: RC.
DH: Mask}
Mov DH,128 {Mask}
Mov EBX,OFFSET TGVConfig.GVNumArr-1 {I}
Mov ECX,-1 {RC}
XOr ESI,ESI
{-----------}
@@01:RoL DH,1
AdC EBX,ESI
Inc ECX
Mov DL,[EDI+EBX]
And DL,DH
Sub DL,DH
SbB EAX,ESI
JNE @@01
{-----------}
Or [EDI+EBX],DH
Dec DWord Ptr [EDI+OFFSET TGVConfig.GVNumArrAmount]
Add ECX,[EDI+OFFSET TGVConfig.GVNumArrMin]
Mov EAX,ECX
@@00:Pop EDI
Pop ESI
Pop EBX
End;
Procedure RndGVNum_Test(GVMin,GVMax:Integer);
Var Num,Max,Count:Integer;
GVConfig:TGVConfig;
Begin
MyInitRand;
Count:=0;
ReSetGVConfig(GVConfig,GVMin,GVMax);
Max:=GVConfig.GVNumArrMin+
GVConfig.GVNumArrAmount-1;
WriteLn;
While (CopyInt(GetRndGVNum(GVConfig),@Num)<>MinCellValue) Do
Begin
Write(Num,#9);
Inc(Count);
End;
WriteLn;
WriteLn;
WriteLn('Minimum value:');
WriteLn(GVMin);
WriteLn('Maximum value:');
WriteLn(GVMax);
WriteLn('New minimum value:');
WriteLn(GVConfig.GVNumArrMin);
WriteLn('New maximum value:');
WriteLn(Max);
WriteLn('Maximum allowed value:');
WriteLn(GVConfig.GVNumArrMin+MaxDeltaNum);
WriteLn('Maximum extraction width:');
WriteLn(MaxDeltaNum+1);
WriteLn('Total number of numbers generated:');
WriteLn(Count);
WriteLn;
WriteLn('ALL NUMBERS HAVE BEEN EXTRACTS!');
WriteLn('Try extraction of other 3 numbers:');
WriteLn;
WriteLn(GetRndGVNum(GVConfig));
WriteLn(GetRndGVNum(GVConfig));
WriteLn(GetRndGVNum(GVConfig));
WriteLn;
Write('Press ENTER to exit ... ');
ReadLn;
End;
End.