Einzelnen Beitrag anzeigen

alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#10

Re: Zufallszahlen im Bereich Von-Bis, ohne Zurücklegen

  Alt 5. Jul 2008, 06:05
Ich muss doch einige gravierende Design- und Ästhetikfehler anmerken:
1. Der Klassenname ist eine Zumutung (Klare verständliche Bezeichner verwenden).
2. Es werden sowohl deutsche als auch englische Bezeichner verwendet (Für eine Sprache und eine Formulierung entscheiden).
3. Die verwendete Methode ist suboptimal, sie kann in Extremfällen sehr lange dauern, wenn nämlich der RNG partout nur bereits gezogene Zahlen liefert.
4. Der Parameter 'Unique' ist überflüssig, denn dann kann ich auch gleich den normalen RNG Random verwenden.

Hier ein wesentlich kompakterer Gegenvorschlag:
Delphi-Quellcode:
type
  ENoMoreNumbers = Exception;
  TUniqueRandomSequenceGenerator = class
  private
    FCounter: Integer;
    FNumberList: array of Integer;
  public
    constructor Create(aStart, aEnde: Integer);
    procedure BuildSequence(aStart, aEnde: Integer);
    function GetNextNumber: Integer;
    function TotalCount: Integer;
    function RemainingCount: Integer;
  end;
implementation

{ TUniqueRandomGenerator }

constructor TUniqueRandomSequenceGenerator.Create(aStart, aEnde: Integer);
begin
  BuildSequence(aStart, aEnde);
end;

procedure TUniqueRandomSequenceGenerator.BuildSequence(aStart, aEnde: Integer);
var
  i, j, tmp: Integer;

begin
  SetLength(FNumberList, aEnde - aStart + 1);
// Zahlenliste erzeugen
  for i := 0 to TotalCount - 1 do
    FNumberList[i] := aStart + i;

// Mischen nach Fisher-Yates
  for i := Low(FNumberList) to High(FNumberList) do begin
    j := i + Random(Length(FNumberList) - i);
    tmp := FNumberList[j];
    FNumberList[j] := FNumberList[i];
    FNumberList[i] := tmp;
  end;
  FCounter := 0;
end;

function TUniqueRandomSequenceGenerator.GetNextNumber: Integer;
begin
  if FCounter < High(FNumberList) then begin
    Result := FNumberList[FCounter];
    Inc(FCounter);
  end
  else raise ENoMoreNumbers.Create('No more numbers');
end;

function TUniqueRandomSequenceGenerator.RemainingCount: Integer;
begin
  Result := TotalCount - FCounter;
end;

function TUniqueRandomSequenceGenerator.TotalCount: Integer;
begin
  Result := Length(FNumberList);
end;
Hintergrund: Ich erzeuge eine Liste aller Zahlen und mische diese Liste dann zufällig. Das verwendete Mischverfahren beweisbar perfekt, ergo liefert die Klasse gleichverteilte Zufallszahlen.
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat