2020-03-30 18:01:44 +00:00
|
|
|
unit BinomialUnit;
|
|
|
|
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
|
|
|
|
interface
|
|
|
|
|
|
|
|
uses
|
|
|
|
Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
|
|
|
|
StdCtrls, ExtCtrls,
|
|
|
|
OutputUnit, FunctionsLib, GraphLib;
|
|
|
|
|
|
|
|
type
|
|
|
|
|
|
|
|
{ TBinomialFrm }
|
|
|
|
|
|
|
|
TBinomialFrm = class(TForm)
|
|
|
|
Bevel1: TBevel;
|
|
|
|
Panel1: TPanel;
|
|
|
|
PlotChk: TCheckBox;
|
|
|
|
ResetBtn: TButton;
|
|
|
|
ComputeBtn: TButton;
|
2020-05-10 10:37:19 +00:00
|
|
|
CloseBtn: TButton;
|
2020-03-30 18:01:44 +00:00
|
|
|
FreqAEdit: TEdit;
|
|
|
|
FreqBEdit: TEdit;
|
|
|
|
PropAEdit: TEdit;
|
|
|
|
Label1: TLabel;
|
|
|
|
Label2: TLabel;
|
|
|
|
Label3: TLabel;
|
|
|
|
procedure ComputeBtnClick(Sender: TObject);
|
|
|
|
procedure FormActivate(Sender: TObject);
|
|
|
|
procedure FormCreate(Sender: TObject);
|
|
|
|
procedure FormShow(Sender: TObject);
|
|
|
|
procedure ResetBtnClick(Sender: TObject);
|
|
|
|
private
|
|
|
|
function Validate(out AMsg: String; out AControl: TWinControl): Boolean;
|
|
|
|
{ private declarations }
|
|
|
|
public
|
|
|
|
{ public declarations }
|
|
|
|
end;
|
|
|
|
|
|
|
|
var
|
|
|
|
BinomialFrm: TBinomialFrm;
|
|
|
|
|
|
|
|
implementation
|
|
|
|
|
|
|
|
uses
|
|
|
|
Math;
|
|
|
|
|
|
|
|
{ TBinomialFrm }
|
|
|
|
|
|
|
|
procedure TBinomialFrm.ResetBtnClick(Sender: TObject);
|
|
|
|
begin
|
|
|
|
FreqAEdit.Text := '';
|
|
|
|
FreqBEdit.Text := '';
|
|
|
|
PropAEdit.Text := '';
|
|
|
|
FreqAEdit.SetFocus;
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TBinomialFrm.FormActivate(Sender: TObject);
|
|
|
|
var
|
|
|
|
w: Integer;
|
|
|
|
begin
|
2020-05-10 10:37:19 +00:00
|
|
|
w := MaxValue([ResetBtn.Width, ComputeBtn.Width, CloseBtn.Width]);
|
2020-03-30 18:01:44 +00:00
|
|
|
ResetBtn.Constraints.MinWidth := w;
|
|
|
|
ComputeBtn.Constraints.MinWidth := w;
|
2020-05-10 10:37:19 +00:00
|
|
|
CloseBtn.Constraints.MinWidth := w;
|
2020-03-30 18:01:44 +00:00
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TBinomialFrm.FormCreate(Sender: TObject);
|
|
|
|
begin
|
|
|
|
if GraphFrm = nil then
|
|
|
|
Application.CreateForm(TGraphFrm, GraphFrm);
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TBinomialFrm.FormShow(Sender: TObject);
|
|
|
|
begin
|
|
|
|
ResetBtnClick(self);
|
|
|
|
end;
|
|
|
|
|
|
|
|
procedure TBinomialFrm.ComputeBtnClick(Sender: TObject);
|
|
|
|
var
|
|
|
|
p, Q, Probability, z, CorrectedA, SumProb : double;
|
|
|
|
A, b, N, X, i: integer;
|
|
|
|
lReport: TStrings;
|
|
|
|
msg: String;
|
|
|
|
C: TWinControl;
|
|
|
|
begin
|
|
|
|
if not Validate(msg, C) then begin
|
|
|
|
C.SetFocus;
|
|
|
|
MessageDlg(msg, mtError,[mbOK], 0);
|
|
|
|
ModalResult := mrNone;
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
|
|
|
|
SumProb := 0.0;
|
|
|
|
A := round(StrToFloat(FreqAEdit.Text));
|
|
|
|
b := round(StrToFloat(FreqBEdit.Text));
|
|
|
|
p := StrToFloat(PropAEdit.Text);
|
|
|
|
N := A + b;
|
|
|
|
Q := 1.0 - p;
|
|
|
|
|
|
|
|
lReport := TStringList.Create;
|
|
|
|
try
|
|
|
|
lReport.Add('BINOMIAL PROBABILITY TEST');
|
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('Frequency of %d out of %d observed', [A, N]);
|
2020-05-10 10:37:19 +00:00
|
|
|
lReport.Add('The theoretical proportion expected in category A is %.f', [p]);
|
2020-03-30 18:01:44 +00:00
|
|
|
lReport.Add('');
|
|
|
|
lReport.Add('The test is for the probability of a value in category A as small or smaller');
|
|
|
|
lReport.Add('than that observed given the expected proportion.');
|
|
|
|
|
2020-05-10 10:37:19 +00:00
|
|
|
//Use normal distribution approximation
|
|
|
|
if (N > 35) then
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
|
|
|
CorrectedA := A;
|
|
|
|
if A < N * p then CorrectedA := A + 0.5;
|
|
|
|
if A > N * p then CorrectedA := A - 0.5;
|
|
|
|
z := (CorrectedA - N * p) / sqrt(N * p * Q);
|
|
|
|
lReport.Add('Z value for Normal Distribution approximation: %.3f', [z]);
|
|
|
|
Probability := probz(z);
|
2020-05-10 10:37:19 +00:00
|
|
|
lReport.Add('Probability: %6.4f', [Probability]);
|
|
|
|
end else
|
|
|
|
//Use binomial fomula
|
2020-03-30 18:01:44 +00:00
|
|
|
begin
|
|
|
|
for X := 0 to A do
|
|
|
|
begin
|
2020-05-10 10:37:19 +00:00
|
|
|
Probability := combos(X, N) * Power(p, X) * Power(Q, N - X);
|
|
|
|
lReport.Add('Probability of %2d: %6.4f', [X, Probability]);
|
2020-03-30 18:01:44 +00:00
|
|
|
SumProb := SumProb + Probability;
|
|
|
|
end;
|
|
|
|
lReport.Add('Binomial Probability of %d or less out of %d: %.4f', [A, N, SumProb]);
|
|
|
|
end;
|
|
|
|
|
|
|
|
DisplayReport(lReport);
|
|
|
|
finally
|
|
|
|
lReport.Free;
|
|
|
|
end;
|
|
|
|
|
|
|
|
if PlotChk.Checked then
|
|
|
|
begin
|
|
|
|
if N <= 35 then
|
|
|
|
begin
|
|
|
|
SetLength(GraphFrm.Xpoints,1,N+1);
|
|
|
|
SetLength(GraphFrm.Ypoints,1,N+1);
|
|
|
|
for i := 0 to N do
|
|
|
|
begin
|
|
|
|
GraphFrm.Xpoints[0,i] := i;
|
|
|
|
Probability := combos(i,N) * power(p,i) * power(Q,(N-i));
|
|
|
|
GraphFrm.Ypoints[0,i] := Probability;
|
|
|
|
end;
|
|
|
|
GraphFrm.GraphType := 2;
|
|
|
|
GraphFrm.nosets := 1;
|
|
|
|
GraphFrm.nbars := N;
|
|
|
|
GraphFrm.BackColor := clCream;
|
|
|
|
GraphFrm.WallColor := clDkGray;
|
|
|
|
GraphFrm.FloorColor := clGray;
|
|
|
|
GraphFrm.Heading := 'Binomial Distribution';
|
|
|
|
GraphFrm.XTitle := 'Values';
|
|
|
|
GraphFrm.YTitle := 'Probability';
|
|
|
|
GraphFrm.barwideprop := 0.5;
|
|
|
|
GraphFrm.AutoScaled := true;
|
|
|
|
GraphFrm.ShowLeftWall := true;
|
|
|
|
GraphFrm.ShowRightWall := true;
|
|
|
|
GraphFrm.ShowBottomWall := true;
|
|
|
|
GraphFrm.ShowModal;
|
|
|
|
GraphFrm.Xpoints := nil;
|
|
|
|
GraphFrm.Ypoints := nil;
|
|
|
|
end else
|
|
|
|
MessageDlg('Cannot plot for N > 35', mtInformation, [mbOK], 0);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
|
|
|
|
function TBinomialFrm.Validate(out AMsg: String; out AControl: TWinControl): Boolean;
|
|
|
|
var
|
|
|
|
x: Double;
|
|
|
|
begin
|
|
|
|
Result := false;
|
|
|
|
if (FreqAEdit.Text = '') or (FreqBEdit.Text = '') or (PropAEdit.Text = '') then
|
|
|
|
begin
|
|
|
|
AMsg := 'Value not specified.';
|
|
|
|
if FreqAEdit.Text = '' then AControl := FreqAEdit;
|
|
|
|
if FreqBEdit.Text = '' then AControl := FreqBEdit;
|
|
|
|
if PropAEdit.Text = '' then AControl := PropAEdit;
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
if not TryStrToFloat(FreqAEdit.Text, x) then
|
|
|
|
begin
|
|
|
|
AMsg := 'No valid number.';
|
|
|
|
AControl := FreqAEdit;
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
if not TryStrToFloat(FreqBEdit.Text, x) then
|
|
|
|
begin
|
|
|
|
AMsg := 'No valid number.';
|
|
|
|
AControl := FreqBEdit;
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
if not TryStrToFloat(PropAEdit.Text, x) then
|
|
|
|
begin
|
|
|
|
AMsg := 'No valid number.';
|
|
|
|
AControl := PropAEdit;
|
|
|
|
exit;
|
|
|
|
end;
|
|
|
|
|
|
|
|
Result := true;
|
|
|
|
end;
|
|
|
|
|
|
|
|
initialization
|
|
|
|
{$I binomialunit.lrs}
|
|
|
|
|
|
|
|
end.
|
|
|
|
|