Funkcja losowa

mike87

Funkcja na podstawie aktualnych informacji pobranych z daty generuje liczby pseudolosowe.
Pobiera z systemu: liczbę milisekund, numer dnia tygodnia, aktualna liczbę sekund oraz aktualną godzinę i z zadanego wzoru oblicza liczbę pseudolosową.
Funkcja ta ma nad funkcją random() taką przewagę, że można podać zakres z którego ma zostać zwrócona wartość.
Funkcję wywołujemy poleceniem:

losowa(min:integer,max:integer)

Jako wynik zwraca wartość z przedziału pomiędzy min i max włącznie (wynik jest typu integer).

UWAGA: Aby funkcja zadziałała prawidłowo należy do sekcji USES dołączyć moduł DateUtils.

function losowa(min:integer;max:integer):integer;
var ms,ms2,ms3,ms4:word;
temp:integer;
begin
if min>max then
  begin;
  temp:=min;
  min:=max;
  max:=temp;
  end;
ms:=MilliSecondOf(Now);
ms2:=WeekOf(Now) div 3;
ms3:=SecondOf(Now) mod 8;
ms4:=HourOf(Now) div 3 mod 5;
result:=((ms*2+ms2*8+ms3*5+ms4*3) mod (max+1-min))+min;
end; 

Poniżej przedstawiam przykład zastosowania. W przykładzie tym po kliknięciu na przycisk Button1 w polu Edit1 pojawi się losowa wartość od 1-6 (tak jak w kostce do gry).

unit generator_losowy;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DateUtils, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
function losowa(min:integer;max:integer):integer;
var ms,ms2,ms3,ms4:word;
temp:integer;
begin
if min>max then
  begin;
  temp:=min;
  min:=max;
  max:=temp;
  end;ms:=MilliSecondOf(Now);
ms2:=WeekOf(Now) div 3;
ms3:=SecondOf(Now) mod 8;
ms4:=HourOf(Now) div 3 mod 5;
result:=((ms*2+ms2*8+ms3*5+ms4*3) mod (max+1-min))+min;
end;
begin
edit1.text:=inttostr(losowa(1,6));
end;

end.

5 komentarzy

a przypisujac na koncu np. edit1.text:=inttostr(losowa(1,100)); to zrobi nam sie kostka k100 ?

Dlatego właśnie funkcja ta właściwie nie nadaje się do stosowania więcej jak raz - ja ją stosuję w połączeniu z funkcją random, dzięki czemu mam dwie liczby pseudolosowe nie powiązane ze sobą w żaden sposób.

A prawda jest taka, że nie ma idealnego generatora liczb losowych, ponieważ takiego po prostu fizycznie nie da się wykonać.


mike87 napisałpodczas pracy z programem w którym potrzebowałem pobranie dwóch zmiennych losowych przy pomocy funkcji random zawsze były to dwie kolejne liczby.
Kolejne? Można uzyskać nawet identyczne!
Bardzo częstym błędem, jest wołanie RANDOMIZE, za każdym razem przed RANDOM.

Można przyjąć, że wartości zwracane przez funkcję RANDOM są wartościami kolejnych komórek długiej tablicy. Po odczytaniu ostatniej wartości wracamy do pierwszej.
Im ta tablica jest dłuższa, tym lepiej. Długość tej tablicy nazywamy okresem generatora. Dany generator dostarcza ZAWSZE ten SAM ciąg wartości. Lecz miejsce, od którego rozpoczynamy odczytywać tą tablicę może zostać zmienione przez procedurę RANDOMIZE. Na podstawie bieżącego czasu RANDOMIZE ustala, która z komórek zostanie odczytana jako pierwsza.

Jeżeli odpowiednio szybko zawołasz wielokrotnie sekwencję: RANDOMIZE; RANDOM, uzyskasz te same wartości!

Jeżeli w programie nie użyjesz RANDOMIZE ani razu, uzyskasz losowe wartości, lecz przy każdym uruchomieniu programu, ciąg wartości będzie ten sam (co może przydać się przy testowaniu).

RANDOMIZE należy w programie użyć raz i tylko raz!!!

Wysupłaj swoją funkcję losującą z "guzikowych" przeszkadzajek, w pętli wypełnij tablicę wartościami funkcji losowa(), wyświetl zawartość tablicy. Co widzisz?
Czy ma to coś wspólnego z losowością?
-----------------------------------------------------------------------------------------------------------[ Xitami ]-

Można to zrobić obejściem (na przykład Random(5)+10), ale ta funkcja została napisana z inną myślą. To znaczy podczas pracy z programem w którym potrzebowałem pobranie dwóch zmiennych losowych przy pomocy funkcji random zawsze były to dwie kolejne liczby. Teraz używam do generowania pierwszej liczby funkcji Random(), natomiast do drugiej liczby funkcji Losowa().

A w funkcji Random() nie można podać zakreesu?