Sign in Join
Wiki copytemporary

Delphi compatible LCG Random: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: Delphi compatible LCG Random

OldNewLine
1+### Delphi compatible random numbers
2+
3+Many Free Pascal programmers also maintain sourcecode in Delphi.\
4+Even if you have moved to Free Pascal from Delphi you may have data that relies on Delphi's Random.\
5+Here are cross-platform functions that generate Delphi-identical pseudo-random numbers given the same RandSeed:
6+
7+``` pascal
8+unit lcg_random;
9+// Delphi compatible LCG random number generator routines for Free Pascal.
10+// (c)2017, Thaddy de Koning. Use as you like
11+// Algorithm, Delphi multiplier and increment taken from:
12+// https://en.wikipedia.org/wiki/Linear_congruential_generator
13+// The default Delphi RandomSeed is determined as zero.
14+{$ifdef fpc}{$mode objfpc}{$endif}
15+
16+interface
17+
18+function LCGRandom: extended; overload;inline;
19+function LCGRandom(const range:longint):longint;overload;inline;
20+
21+implementation
22+
23+function IM:cardinal;inline;
24+begin
25+ RandSeed := RandSeed * 134775813 + 1;
26+ Result := RandSeed;
27+end;
28+
29+function LCGRandom: extended; overload;inline;
30+begin
31+ Result := IM * 2.32830643653870e-10;
32+end;
33+
34+function LCGRandom(const range:longint):longint;overload;inline;
35+begin
36+ Result := IM * range shr 32;
37+end;
38+
39+end.
40+```
41+
42+\
43+A small demo
44+
45+``` pascal
46+program lcgdemo;
47+// Compile and run in both Delphi and FPC and compare the output.
48+// It is exactly the same
49+{$ifdef fpc}{$mode objfpc}
50+{$Macro on}{$define random := LCGRandom}
51+{$endif}
52+{$ifdef mswindows}{$apptype console}{$endif}
53+uses lcg_random;
54+
55+var i:integer;
56+begin
57+ RandSeed := 999; // default delphi randseed is zero
58+ for i := 1 to 20 do
59+ begin
60+ write(Random(100):4); // Delphi: Random FPC:LCGRandom. See macro
61+ if i mod 5 = 0 then writeln;
62+ end;
63+
64+ RandSeed := 999; // default delphi randseed is zero
65+ for i := 1 to 20 do
66+ begin
67+ write(Random:4:8,' ');// Delphi: Random FPC:LCGRandom
68+ if i mod 5 = 0 then writeln;
69+ end;
70+ Readln;
71+end.
72+```
73+
74+Here is another one with the randseed factored out. You can use that for non-delphi compatible purposes:
75+
76+``` pascal
77+unit lcg_random2;
78+// Delphi compatible LCG random number generator routines for Freepascal.
79+// (c)2017, Thaddy de Koning. Use as you like
80+// Algorithm, Delphi multiplier and increment taken from:
81+// https://en.wikipedia.org/wiki/Linear_congruential_generator
82+// The default Delphi RandomSeed is determined as zero.
83+//
84+// In this version the system randseed is factored out.
85+{$ifdef fpc}{$mode objfpc}{$endif}{$J+}
86+
87+interface
88+const
89+ RandSd:cardinal = 0;
90+
91+function LCGRandom: extended; overload;inline;
92+function LCGRandom(const range:longint):longint;overload;inline;
93+
94+implementation
95+
96+function IM:cardinal;inline;
97+begin
98+ RandSd := RandSd * 134775813 + 1;
99+ Result := RandSd;
100+end;
101+
102+function LCGRandom: extended; overload;inline;
103+begin
104+ Result := IM * 2.32830643653870e-10;
105+end;
106+
107+function LCGRandom(const range:longint):longint;overload;inline;
108+begin
109+ Result := IM * range shr 32;
110+end;
111+
112+end.
113+```
114+
115+You can use this for example for simple encryption and decryption based on the predictability and repeatability of a any Pseudo Random Number Generator:
116+
117+``` pascal
118+program cryptrandom;
119+{$mode objfpc}{$modeswitch typehelpers}{$H+}
120+{ This is demo that you can actually use random to encrypt/decrypt.
121+ This is due to the nature of a Pseudo Random Number Generator,
122+ where given a certain random seed, the sequence is predictable.
123+ Here I use the Random Seed as a key to encrypt/decrypt a string.
124+ The same code would also work with the Default random from FreePascal,
125+ but it is better not to touch system.randseed, So I used a different
126+ Random.
127+
128+ Have fun, Thaddy}
129+uses
130+lcg_random2;
131+
132+
133+function Crypt(const value:AnsiString;const Key:Cardinal):AnsiString;
134+var
135+ i:integer;
136+begin
137+ RandSd := Key;
138+ SetLength(Result,Length(Value));
139+ for i := 1 to length(Value) do
140+ Result[i] := Chr(Ord(Value[i]) xor lcgrandom(255));
141+end;
142+
143+var
144+ a:AnsiString;
145+begin
146+ a:='This is the text to encrypt/decrypt.';
147+ writeln(a);
148+ writeln('Encrypting..');
149+ a:=Crypt(a, 12345);
150+ writeln(a);
151+ writeln('Decrypting..');
152+ a:=Crypt(a, 12345);
153+ writeln(a);
154+end.
155+```
156+
157+### See also
158+
159+1. [LCG on wikipedia](https://en.wikipedia.org/wiki/Linear_congruential_generator)
160+2. [[Generating Random Numbers]]
161+
162+## See also
163+
164+- [Wikipedia article on the linear congruential generator algorithm](http://en.wikipedia.org/wiki/Linear_congruential_generator)
165+
166+---
167+*From the Free Pascal wiki, page "Delphi compatible LCG Random", as it stood on 2024-05-14 after a change by Alextp, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
168+Category: Modelling and Simulation
169+Category: Statistical algorithms

Back to history