Ho trovato una soluzione.
Il blog di Controul di Hristo Dachev descrive diversi metodi, di cui Ho implementato il Marsaglia polar method
.
Il codice Delphi per un'implementazione rapida e sporca con una distribuzione normale standard (moltiplicata per contare i valori integer) è inferiore.
Il blog fa riferimento al articolo di Wikipedia che ha uno pseudo codice per qualsiasi media e deviazione standard.
Distribuzione di esempio generata dal programma (10000 punti):
File.pasDelphiXE2:
unituMarsaglia;//Basedonhttp://blog.controul.com/2009/04/standard-normal-distribution-in-as3///Referstohttp://en.wikipedia.org/wiki/Marsaglia_polar_methodinterfaceusesWinapi.Windows,Winapi.Messages,System.SysUtils,System.Variants,System.Classes,Vcl.Graphics,System.Math,Vcl.Controls,Vcl.Forms,Vcl.Dialogs,VCLTee.TeEngine,Vcl.ExtCtrls,VCLTee.TeeProcs,VCLTee.Chart,Vcl.StdCtrls,VCLTee.Series;typeTFrmMarsaglia=class(TForm)Chart1:TChart;Series1:TBarSeries;procedureFormShow(Sender:TObject);privateFReady:Boolean;FCache:Real;functionStandardNormal:Real;publicend;varFrmMarsaglia:TFrmMarsaglia;implementation{$R*.dfm}functionLn(R:Real):Real;beginResult:=Log10(R)/Log10(2.7182818);end;procedureTFrmMarsaglia.FormShow(Sender:TObject);constcTestMax=1000000;cScale=1000;cMaxScale=5*cScale;//Wedon'tcountgeneratednumbershigherthanthatvarA:Array[1..cMaxScale]ofInteger;i:integer;lMax,Nr:Integer;rScale:Real;beginforNr:=1tocMaxScaledoA[Nr]:=0;rScale:=cScale;forNr:=1tocTestMaxdobegini:=Trunc(rScale*StandardNormal);ifi<=cMaxScalethenInc(A[i]);end;lMax:=0;forNr:=1tocMaxScaledoifA[Nr]>lMaxthenlMax:=A[Nr];Series1.Clear;forNr:=1tocMaxScaledoSeries1.Add(A[Nr]);end;functionTFrmMarsaglia.StandardNormal:Real;//ReturnsrealnumbersbetweenN(0,1)thatwhenrepeatedhaveanormaldistributionvarx,y,w,l:Real;beginifFReadythenbegin//Returnacachedresultfromapreviouscallifavailable.FReady:=false;Result:=FCache;Exit;end;//Repeatextractinguniformvaluesintherange(-1,1)until0<w=x*x+y*y<1repeatx:=Random;y:=Random;w:=x*x+y*y;until(w>0)and(w<1);l:=Ln(w);w:=sqrt(-2*l/w);FReady:=true;FCache:=x*w;//CacheoneoftheoutputsResult:=y*w;//andreturntheother.end;end.
Delphi.frmfilecheutilizzaunTChart( TeeChart ) che mostra i risultati:
object FrmMarsaglia: TFrmMarsaglia
Left = 0
Top = 0
Caption = 'Marsaglia polar method'
ClientHeight = 626
ClientWidth = 964
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'Tahoma'
Font.Style = []
OldCreateOrder = False
OnShow = FormShow
PixelsPerInch = 96
TextHeight = 13
object Chart1: TChart
Left = 0
Top = 0
Width = 964
Height = 626
BackWall.Visible = False
BottomWall.Visible = False
Foot.Visible = False
LeftWall.Visible = False
Legend.Visible = False
Title.Text.Strings = (
'TChart')
Title.Visible = False
View3D = False
Align = alClient
BevelOuter = bvNone
TabOrder = 0
ExplicitLeft = 272
ExplicitWidth = 692
ColorPaletteIndex = 13
object Series1: TBarSeries
Marks.Arrow.Visible = True
Marks.Callout.Brush.Color = clBlack
Marks.Callout.Arrow.Visible = True
Marks.Visible = False
XValues.Name = 'X'
XValues.Order = loAscending
YValues.Name = 'Bar'
YValues.Order = loNone
end
end
end
Si noti che 'non tenere una cronologia' non è soddisfatto: c'è un booleano e un numero reale da ricordare stato. Questo è abbastanza buono per me; Avevo paura di dover mantenere matrici di numeri già generati.