Einzelnen Beitrag anzeigen

Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#66

Re: Unbegrenzt viele Nachkommastellen

  Alt 24. Sep 2004, 12:50
NRnd(var A: IInteger; Bits: Integer = 0; Sign: Boolean = False; Random: TRandom = nil); overload; Bits gibt dabei die Größe=Wertebereich des IInteger's in A an der erzeugt werden soll.
Also bei NRnd(A, 64); wird A im Bereich von 2^63 <= A < 2^64 sein, ergo A hat garantiert eine Größe von 64 Bits. Dieses Verhalten ist bei der Anwendung von großen Zahlen, sei es für Kryptographie, Mathematik ect. pp. am häufigsten erwünscht. Meistens muß man eben Zufallszahlen erzeugen (zb. Primzahlen) die exakt X Bits groß sind.

Wird Sign == TRUE gesetzt so wird auch das Vorzeichen per Zufall erzeugt, ansonsten bleibt es wie es ist.

Du kannst aber auch Bits == 0 übergeben. Dann wird intern Bits per Zufall im Bereich von 1 bis 2048 liegen, d.h. die Function NRnd() erzeugt dann Zufallszahlen im Bereich von 0 <= A < 2^2048

Statt NCut() hättest du dann NBit(A, NHigh(A), False); nehmen können, dies dürfte schneller sein.

Wie du am nachfolgendem Source von NRnd() erkennen kannst kann Bits < 0 sein. Zb. mit NRnd(A, -64); würdest du Zahlen im Bereich von 0 <= A < 2^64 erzeugen. Also im Grunde das was du suchtest. Ok, der negative Bits Parameter ist ziemlich versteckt allerdings benötigt man solche Zufallszahlen fast niemals. Zumindestens ich brauchte diese Funktionalität nur ein einzigstes mal bisher.

Dein NCut() Aufruf wirkt mathematisch wie ein NMod(A, 2^16), sprich Modulare Division.
Falls du Zb. Zahlen im Bereich von 100.000 <= A < 1.000.000 erzeugen wolltest dann sähe dies so aus

Delphi-Quellcode:
  NRnd(A, -32);
  NMod(A, 1000000 - 100000);
  NAdd(A, 100000);
Gruß Hagen


Delphi-Quellcode:
procedure NRnd(var A: IInteger; Bits: Integer = 0; Sign: Boolean = False; Random: TRandom = nil);
var
  I: Integer;
begin
  with NAllocNew(A)^ do
  begin
    if Random = nil then Random := RND;
    if Bits = 0 then Bits := Random.Int(256 * 8);
    if Bits = 0 then
    begin
      FCount := 0;
      FNeg := False;
    end else
    begin
      if Bits < 0 then
      begin
        Bits := -Bits;
        I := (Bits + 31) shr 5;
        if Cardinal(I) > FSize then NSetCount(A, I, cfNoFill) else FCount := I;
        Random.Buffer(FNum^, I * 4);
        Dec(I);
        Bits := FNum[I] and ($FFFFFFFF shr (32 - Bits and 31));
        FNum[I] := Bits;
        if Bits = 0 then NNormalize(A);
      end else
      repeat
        I := (Bits + 31) shr 5 +1;
        if Cardinal(I) > FSize then NSetCount(A, I, cfNoFill) else FCount := I;
        Random.Buffer(FNum^, I * 4);
        if FNum[I] = 0 then NNormalize(A);
        I := NSize(A) - Bits;
        if I > 0 then NShr(A, I);
      until I >= 0;
      if Sign then FNeg := Random.Int(2) = 1;
    end;
  end;
end;
  Mit Zitat antworten Zitat