Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.063 Beiträge
 
Delphi 12 Athens
 
#38

AW: Besseres Random() - eure Vorschläge

  Alt 7. Jul 2020, 20:31
Inzwischen sind die Funktionen "auch" als Pure-Pascal verfügbar (für andere Platformen wo dieser Assembler nicht läuft)
und was ich grad bemerkte und als besonders praktisch empfand, wurden dort irgendwann zwei Variablen eingebaut, so dass man da ein eigenes Random (IntRandom) und Randomize registrieren und es somit auch "überall" im Delphi austauschen kann.

PS: Das aus #30 noch ein bissl zusammengefasst, dann kommt das bei raus.
Delphi-Quellcode:
function ra(aRange: Integer): Integer;
begin
  RandSeed := RandSeed * 134775813 + 1; // 3*17*131*20173
  Result := (Int64(aRange) * RandSeed) shr 32; // aka Result := MulDiv(aRange, RandSeed, $100000000);
end;
Aber die Grundlagen des "deterministic linear congruential generator with 134775813 as a and 1 as c" haben sich nicht geändert.
Das ist seit über 20 Jahren konstant. Nur wurde vor längerer Zeit mal das GetTickCount gegen QueryPerformanceCounter im Randomize ersetzt, womit ein "falsch" benutztes und zu oft/schnell aufgerufenes Randomize keine großen Nachteile bringt.

Delphi-Quellcode:
type
  TRandom32Proc = function: UInt32;
  TRandomizeProc = procedure(NewSeed: UInt64);

function DefaultRandom32: UInt32;
procedure DefaultRandomize(NewSeed: UInt64);

var
  Random32Proc: TRandom32Proc = DefaultRandom32;
  RandomizeProc: TRandomizeProc = DefaultRandomize;

procedure Randomize;

function Random(const ARange: Integer): Integer; overload;
function Random: Extended; overload;



function DefaultRandom32: UInt32;
{$IFDEF PUREPASCAL}
begin
  Result := UInt32(RandSeed) * $08088405 + 1;
  RandSeed := Result
end;
{$ELSE !PUREPASCAL}
asm
{     <-EAX     Result  }
{$IFDEF PIC}
        PUSH EBX
        CALL GetGOT
        MOV EBX,EAX
        MOV ECX,[EBX].RandSeed
        IMUL EAX,[ECX],08088405H
        INC EAX
        MOV [ECX],EAX
        POP EBX
{$ELSE !PIC}
        IMUL EAX,RandSeed,08088405H
        INC EAX
        MOV RandSeed,EAX
{$ENDIF !PIC}
end;
{$ENDIF !PUREPASCAL}

function Random(const ARange: Integer): Integer;
{$IFDEF PUREPASCAL}
var
  Temp: UInt32;
begin
  Temp := Random32Proc;
  Result := (UInt64(UInt32(ARange)) * UInt64(Temp)) shr 32;
end;
{$ELSE !PUREPASCAL}
asm
{     ->EAX     Range   }
{     <-EAX     Result  }
{$IFDEF PIC}
        PUSH EBX
        PUSH EAX
...
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.

Geändert von himitsu ( 7. Jul 2020 um 21:45 Uhr)
  Mit Zitat antworten Zitat