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, Messages, SysUtils, Variants, Classes,
Graphics, Controls, Forms, Dialogs, StdCtrls;
type
TSzamol=Class(TThread)
Private
X, Y: Integer;
Protected
Procedure Execute; OverRide;
Procedure Szamol;
End;
TfmPi = class(TForm)
lbPi: TLabel;
btKilepes: TButton;
btStart: TButton;
procedure btKilepesClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure btStartClick(Sender: TObject);
private
{ Private declarations }
Sz: TSzamol;
public
{ Public declarations }
end;
Const R= 300;
var
fmPi: TfmPi;
Xk, Yk: Integer;
N, K: LongInt;
Bent: Boolean;
implementation
{$R *.dfm}
procedure TfmPi.btKilepesClick(Sender: TObject);
begin
Close;
end;
procedure TfmPi.FormCreate(Sender: TObject);
begin
Randomize;
Xk:= ClientWidth Div 2;
Yk:= ClientHeight Div 2;
N:= 0; K:= 0;
end;
procedure TfmPi.FormPaint(Sender: TObject);
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(Sender: TObject);
begin
btStart.Enabled:= False;
Sz:= TSzamol.Create(False);
end;
end.