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)所需的所有功能。如果是这样,您可以使用以下公式计算下一个伪随机数

acm值上有三个限制

  • mc是相对优质的
  • a-1可被m的所有素数因子整除
  • a-1可被4整除,如果m可被4整除

  • 有关详细信息,请参见wiki。

    对不起,我不熟悉uBigIntsV4。我希望它具有实现基本算术运算(*,+,mod)所需的所有功能。如果是这样,您可以使用以下公式计算下一个伪随机数

    acm值上有三个限制

  • mc是相对优质的
  • a-1可被m的所有素数因子整除
  • a-1可被4整除,如果m可被4整除

  • 有关详细信息,请参见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.