A Pi közelítése a geometriai valószínűség segítségével

 

         Ha egy A korlátos, mérhető területű geometriai alakzat P pontját véletlenszerűen választjuk ki, akkor annak a valószínűsége, hogy az A-nak a B mérhető területű részhalmazára esik: (B mértéke) / (A mértéke). Ezt a valószínűséget (mivel a valószínűség meghatározásához geometriai mértéket kell meghatározni), geometriai valószínűségnek nevezzük.

 

         A geometriai valószínűség fogalma lehetőséget kínál területek mérőszámának közelítésére. Ha egy négyzetbe egy, az oldalait érintő kört rajzolunk, majd az alakzat pontjait véletlenül választjuk ki elég sokszor, akkor a körre eső pontok száma úgy aránylik a négyzetre eső (összes pont) számához, mint a kör területe a négyzet területéhez. Képletben: R2*Pi / 4*R2. Ha e törtet egyszerűsítjük, akkor a valószínűségre Pi / 4 adódik.

 

Nincs más feladatunk, mint folyamatosan véletlenül választani a négyzet területéről egy pontot, ezt számolni (N) és megnézni, hogy a kör területére esett-e, ha igen akkor azt külön számoljuk (K). Mindig kiírathatjuk a programmal a 4*N/K értéket, mely a Pi értékét közelíti. (Hogy a rajz mindig változzon, a kör területére eső pontoknál nem beállítódik a piros szín, hanem újonnan történő kiválasztáskor a háttérszínnel váltakozik. Így soha nem lesz a kör területe homogén piros. Ugyanígy van a körre nem eső pontoknál is, csak kék színnel.)

 

         Mivel a program leállítási feltételt nem tartalmaz, gondoskodni kell a folyamatos végrehajtás mellett a leállíthatóságról is. Ezt elegánsan egy programozási szál indításával oldhatjuk meg. Az indítást a Start feliratú nyomógomb végzi, melyet megnyomva Enabled tulajdonságát False-ra változtatjuk, mert újabb megnyomása a programot leállíthatatlanná tenné. A képernyőn folyamatosan látjuk a Pi tényleges értékét, a közelítő értéket, valamint a pontválasztások számát.

 

         A futási kép, miközben a gép átlépte a 20 millió pontválasztást:

 

 

         A program listája:

 

unit UPi;

interface

uses
  Windows, MessagesSysUtilsVariantsClasses,

  GraphicsControlsFormsDialogsStdCtrls;

type
  TSzamol=Class(TThread)
    Private
      X, Y: Integer;
      Protected
        Procedure ExecuteOverRide;
        Procedure Szamol;
  End;

  TfmPi = class(TForm)
    lbPiTLabel;
    btKilepesTButton;
    btStartTButton;
    procedure btKilepesClick(SenderTObject);
    procedure FormCreate(SenderTObject);
    procedure FormPaint(SenderTObject);
    procedure btStartClick(SenderTObject);
  private
    Private declarations }
    SzTSzamol;
  public
    Public declarations }
  end;

Const R= 300;

var
  fmPiTfmPi;
  XkYk: Integer;
  N, K: LongInt;
  Bent: Boolean;

implementation

{$R *.dfm}

procedure TfmPi.btKilepesClick(SenderTObject);
begin
  Close;
end;

procedure TfmPi.FormCreate(SenderTObject);
begin
  Randomize;
  Xk:= ClientWidth Div 2;
  Yk:= ClientHeight Div 2;
  N:= 0; K:= 0;
end;

procedure TfmPi.FormPaint(SenderTObject);
begin
  With Canvas Do
  Begin
    Pen.Color:= clBlue;
    Rectangle(Xk-R,Yk-R,Xk+R,Yk+R);
    Pen.Color:= clRed;
    Arc(Xk-R,Yk-R,Xk+R,Yk+R,Xk+R,Yk+R,Xk+R,Yk+R);
    Font.Size:= 12;
    TextOut(10,100,'Pi: 3,14159265358979');
  End;
end;

Procedure TSzamol.Execute;
Begin
  Repeat
    X:= Random(2*R+1)-R;
    Y:= Random(2*R+1)-R;
    Inc(N); Bent:= False;
    If Sqr(X)+Sqr(Y)<=Sqr(R) Then
    Begin Bent:= True; Inc(K) End;
    Synchronize(Szamol);
  Until Terminated;
End;

Procedure TSzamol.Szamol;
Begin
  With fmPi.Canvas Do
  Begin
    If Bent Then
    If Pixels[Xk+X,Yk+Y]= clRed Then
    Pixels[Xk+X,Yk+Y]:= clBtnFace Else
    Pixels[Xk+X,Yk+Y]:= clRed;
    If Not Bent Then
    If Pixels[Xk+X,Yk+Y]= clBlue Then
    Pixels[Xk+X,Yk+Y]:= clBtnFace Else
    Pixels[Xk+X,Yk+Y]:= clBlue;
    Font.Size:= 12;
    TextOut(10,120,'Pi~ '+FloatToStr(4*K/N));
    TextOut(10,150,'N:  '+IntToStr(N));
  End;
End;

procedure TfmPi.btStartClick(SenderTObject);
begin
  btStart.Enabled:= False;
  Sz:= TSzamol.Create(False);
end;

end.