📄 cpwrand.pas
字号:
{*********************************************}
{ }
{ COMPONENT for MS DOS and MS WINDOWS }
{ }
{ Source code for Turbo Pascal 6.0 and }
{ Turbo Pasacal for Windows 1.0 compilers. }
{ }
{ (c) 1991, Roderic D. M. Page }
{ }
{*********************************************}
{$I CPDIR.INC}
unit cpwrand;
{Uniform random number generator. A rewrite of RANDNUM.PAS from COMPONENT 1.5.
<\b History>
26 Nov 1991 Written
}
interface
type
UNIFORM=object
{Encapsulates a uniform random number generator}
constructor Init;
{Initialises by calling [GetSystemSeed]}
procedure SetSeed (UserSeed:longint);
{Sets seed to <\b UserSeed>}
procedure GetSystemSeed;
{Calls <\i Randomize> to initialize Turbo Pascal random number
generator with value from system clock, then calls
<\i Random> to obtain a seed.}
function GetSeed:longint;
{Returns the seed}
function Rand01:real;
{Returns a uniform random number in the range 0-1, using the
recursion:
<\i IX> = <\i IX> x <\i A> mod <\i P>
where <\i IX> is the seed, and <\i A> and <\i P> are constants.
Pascal translation of Schrage's (1979) FORTRAN code
using Turbo Pascal <\i longint> data type. Routine validated
by confirming that if IX(0) = 1 then IX(1000) = 522329230
(i.e. if the first seed is 1 then the 1000th seed is
522329230).
Reference:
Schrage, L. 1979. A more portable Fortran random number
generator. <\i ACM Trans. Math. Software, 5:> 132-138.
}
function RandInteger (Min, Max:longint):longint;
{Returns a uniformly distributed random number from the range
<\b Min> - <\b Max>.
Calls [Rand01] to obtain random number then adjusts using
equation from Bakry and Shatila, (1988: 971). These authors
also give an algorithm for generating uniformly distributed
random numbers, but it requires a machine that can handle
integers \> 2**31-1. This is greater than the limit of Turbo
Pascal's <\i longint> data type, so I have used Schrage's (1979)
algorithm instead (see [Rand01]).
References:
Bakry, S. H. and M. Shatila. 1988. Pascal functions for the
generation of random numbers. <\i Comput. Math. Applic. 15:> 969-973.
Schrage, L. 1979. A more portable Fortran random number
generator. <\i ACM Trans. Math. Software, 5:> 132-138.
}
private
Seed : longint;
end;
implementation
const
P:longint=2147483647;
var
Seed : longint;
{-----------------------------Init-----------------------------------------}
constructor UNIFORM.Init;
begin
GetSystemSeed;
end;
{-----------------------------SetSeed--------------------------------------}
{ let user set the seed }
procedure UNIFORM.SetSeed (UserSeed:longint);
begin
Seed := UserSeed;
end;
{-----------------------------GetSystemSeed--------------------------------}
{ Get a seed from system clock }
procedure UNIFORM.GetSystemSeed;
begin
Randomize;
Seed := Trunc (P * Random) + 1;
end;
{-----------------------------GetSeed--------------------------------------}
function UNIFORM.GetSeed:longint;
begin
GetSeed := Seed;
end;
{-----------------------------Rand01---------------------------------------}
{ Uniform random number generator using the recursion
IX = IX * A mod P
where IX is the seed, and A and P are constants.
Pascal translation of Schrage's (1979) FORTRAN code
using Turbo Pascal longint data type. Routine validated
by confirming that if IX(0) = 1 then IX(1000) = 522329230
(i.e. if the first seed is 1 then the 1000th seed is
522329230).
Reference:
Schrage, L. 1979. A more portable Fortran random number
generator. ACM Trans. Math. Software, 5:132-138.
}
function UNIFORM.Rand01:real;
const
A:longint = 16807;
B15:longint= 32768;
B16:longint= 65536;
var
IX, XALO, XHI, LEFTLO, FHI, K : longint;
begin
IX := Seed;
{ Get 15 hi order bits of IX }
XHI := IX div B16;
{ Get 16 lo bits of IX and form lo product }
XALO := (IX - XHI * B16) * A;
{ Get 15 hi order bits of lo product }
LEFTLO := XALO div B16;
{ Form the 31 highest bits of full product }
FHI := XHI * A + LEFTLO;
{ Get overflow past 31st bit of full product }
K := FHI div B15;
{ Assemble all the parts and presubtract P. The
parentheses are essential }
IX := (((XALO - LEFTLO * B16) - P) + (FHI - K * B15) * B16) + K;
{ Add P back if necessary }
if (IX < 0) then
IX := IX + P;
{ Divide by P to give Rand the range 0-1 }
Rand01 := IX/P;
Seed := IX;
end;
{-----------------------------RandomInteger--------------------------------}
{ Returns a uniformly distributed random number from the range Min-Max.
Equation from Bakry and Shatila, (1988: 971). These authors also give
an algorithm for generating uniformly distributed random numbers, but
it requires a machine that can handle integers > 2**31-1. This is greater
than the limit of Turbo Pascal's longint data type, so I have used
Schrage's (1979) algorithm instead.
References:
Bakry, S. H. and M. Shatila. 1988. Pascal functions for the
generation of random numbers. Comput. Math. Applic. 15:969-973.
Schrage, L. 1979. A more portable Fortran random number
generator. ACM Trans. Math. Software, 5:132-138.
}
function UNIFORM.RandInteger (Min, Max:longint):longint;
begin
RandInteger := Min + Trunc ((Max - Min + 1) * Rand01);
end;
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -