선형 콘그루엔셜 방법(Hull. De bull 제안)
1. 하나의 초기 숫자를 설정(x0)
2. 3개의 상수 a, c, m을 수식에 대입해 난수를 발생시킨다.
3. 다음 조건을 만족해야 한다.
위 알고리즘을 C#으로 표현한 소스는 다음과 같다.
using System;
using System.IO;
using System.Text;
using System.Collections;
namespace TestLCG
{
class Program
{
static void Main(string[] args)
{
if (args.Length != 5)
{
Console.WriteLine("순서) A, C, M, X 초기값, 횟수");
Console.WriteLine("예) LCG.exe 1 63 65535 4 4000");
}
else
{
LCG oLCG;
ArrayList xList;
FileStream fs;
oLCG = new LCG();
oLCG.SetProperty(
long.Parse(args[0])
, long.Parse(args[1])
, long.Parse(args[2])
, long.Parse(args[3])
, long.Parse(args[4])
);
xList= oLCG.RunLCG();
fs = new FileStream(".\\output.txt", FileMode.Create);
StreamWriter sw = new StreamWriter(fs, Encoding.Unicode);
foreach (long xItem in xList)
{
sw.WriteLine(xItem);
}
sw.WriteLine("총 " + xList.Count.ToString() + " 회 진행");
sw.Close();
fs.Close();
}
}
}
/// <summary>
/// LCG(Linear Congruential Generator)
/// </summary>
/// <remarks><para>1. 하나의 초기 숫자를 설정(Xi-1)
/// 2. 3개의 상수에 의한 수식을 대입하여 난수를 발생시킴
/// <code>Xi = (C * [Xi-1] + C) % m</code>
/// 3. A < M, C < M, 0 < M</para></remarks>
[Serializable()]
internal class LCG
{
private long _a;
private long _c;
private long _m;
private long _amount;
/// <summary>
/// First X
/// </summary>
private long _x0;
/// <summary>
/// Current X
/// </summary>
private long _xi;
/// <summary>
/// Count X
/// </summary>
private long _cnt;
/// <summary>
/// X Array List
/// </summary>
private ArrayList _xList;
/// <summary>
/// Interupt
/// </summary>
private long _interupt;
/// <summary>
/// Interupt Count
/// </summary>
private long _cntInterupt;
/// <summary>
/// X Array List
/// </summary>
protected internal ArrayList XList
{
get { return _xList; }
set { _xList = value; }
}
/// <summary>
/// Current X
/// </summary>
protected internal long iXi
{
get { return _xi; }
set { _xi = value; }
}
/// <summary>
/// Count X
/// </summary>
protected internal long iCnt
{
get { return _cnt; }
set { _cnt = value; }
}
/// <summary>
/// Constructor
/// </summary>
public LCG()
{
this.iA = 0;
this.iC = 0;
this.iM = 0;
}
/// <summary>
/// A Const.
/// </summary>
protected internal long iA
{
get { return this._a; }
set { this._a = value; }
}
/// <summary>
/// C Const.
/// </summary>
protected internal long iC
{
get { return this._c; }
set { this._c = value; }
}
/// <summary>
/// M Const.
/// </summary>
protected internal long iM
{
get { return this._m; }
set { this._m = value; }
}
/// <summary>
/// First X
/// </summary>
protected internal long iX0
{
get { return _x0; }
set { _x0 = value; }
}
/// <summary>
/// Maximum count of Calc.
/// </summary>
protected internal long iAmount
{
get { return _amount; }
set { _amount = value; }
}
/// <summary>
/// Set Properties
/// </summary>
/// <param name="a">iA</param>
/// <param name="c">iC</param>
/// <param name="m">iM</param>
/// <param name="x0">iX0</param>
/// <param name="amount">iAmount</param>
protected internal void SetProperty(long a, long c, long m, long x0, long amount)
{
this.iA = a;
this.iC = c;
this.iM = m;
this.iX0 = x0;
this.iXi = x0;
this.iAmount = amount;
this._cntInterupt = 10;
this.XList = new ArrayList();
}
/// <summary>
/// Calc. LCG
/// </summary>
protected internal ArrayList RunLCG()
{
if (this.iA >= this.iM ||
this.iC >= this.iM ||
0 >= iM ||
0 >= iAmount)
{
Console.WriteLine("조건에 맞지 않아 진행할 수 없습니다");
return new ArrayList();
}
for (int i = 0; i < iAmount; i++)
{
this._interupt = -1;
XList.Add((object)this.CalcLCG(this.iXi));
if (this._cntInterupt < this._interupt)
break;
}
return this.XList;
}
/// <summary>
/// Return X1
/// </summary>
protected internal long CalcLCG(long X0)
{
if(this._interupt++>this._cntInterupt)
return -1;
this.iXi = (iA * X0 + iC) % iM;
if (true == this.CheckLCG(this.iXi))
return CalcLCG(this.iXi);
return iXi;
}
/// <summary>
/// Exists of X1
/// </summary>
protected internal bool CheckLCG(long x)
{
return XList.Contains((object)x);
}
}
}