| Snippet | C# | Tools | .NET | Math | Statistics |
SummaryThe .NET Framework provides System.Random for generating random numbers which provides uniform random numbers of type System.Double in the range [0,1). However, in practice one almost always needs random numbers in a different range and often of a different type. I created the RandomProvider class as a more useful wrapper for the Random class and I use it all the time.
|
Example: How to use the RandomProvider Class
public static void TestRandomProvider()
{
Console.WriteLine("Random Double [0,1) = " + RandomProvider.Next());
long ran = RandomProvider.Next(50,100);
Console.WriteLine("Random Int64 [50,100) = " + ran);
Console.WriteLine("Random Boolean = " + RandomProvider.NextBoolean());
DateTime minDT = DateTime.Parse("1/1/1998");
DateTime maxDT = DateTime.Parse("6/1/1998");
DateTime ranDT = RandomProvider.Next(minDT, maxDT);
Console.WriteLine("Random DateTime [1/1/1998, 6/1/1998) = " + ranDT);
TimeSpan minTs = new TimeSpan(3, 0, 0);
TimeSpan maxTs = new TimeSpan(7, 0, 0);
TimeSpan ranTs = RandomProvider.Next(minTs, maxTs);
Console.WriteLine("Random TimeSpan [3 hrs, 7 hrs) = " + ranTs);
Console.WriteLine("Normal deviate = "
+ RandomProvider.NextNormal());
Console.WriteLine("Exponential deviate = "
+ RandomProvider.NextExponential());
} |
| If you run the previous method you'll get something similar to the following output: |
Example: OutputRandom Double [0,1) = 0.147433493820687
Random Int64 [50,100) = 69
Random Boolean = False
Random DateTime [1/1/1998, 6/1/1998) = 2/4/1998 4:09:50 AM
Random TimeSpan [3 hrs, 7 hrs) = 03:58:55.0844951
Normal deviate = 0.277308108809515
Exponential deviate = 1.37058190966813
|
The C# RandomProvider Class:using System;
namespace Cambia.CoreLib
{
/// <summary>
///
///
///
///
/// </summary>
public class RandomProvider
{
private static Random m_RNG1;
private static double m_StoredUniformDeviate;
private static bool m_StoredUniformDeviateIsGood = false;
#region -- Construction/Initialization --
static RandomProvider()
{
Reset();
}
public static void Reset()
{
m_RNG1 = new Random(Environment.TickCount);
}
#endregion
#region -- Uniform Deviates --
/// <summary>
///
/// </summary>
public static double Next()
{
return m_RNG1.NextDouble();
}
/// <summary>
///
/// </summary>
public static bool NextBoolean()
{
if (m_RNG1.Next(0,2) == 0)
return false;
else
return true;
}
/// <summary>
///
/// </summary>
public static double NextDouble()
{
double rn = m_RNG1.NextDouble();
return rn;
}
/// <summary>
///
/// </summary>
public static Int16 Next(Int16 min, Int16 max)
{
if (max <= min)
{
string message = "Max must be greater than min.";
throw new ArgumentException(message);
}
double rn = (max*1.0 - min*1.0)*m_RNG1.NextDouble() + min*1.0;
return Convert.ToInt16(rn);
}
/// <summary>
///
/// </summary>
public static int Next(int min, int max)
{
return m_RNG1.Next(min, max);
}
/// <summary>
///
/// </summary>
public static Int64 Next(Int64 min, Int64 max)
{
if (max <= min)
{
string message = "Max must be greater than min.";
throw new ArgumentException(message);
}
double rn = (max*1.0 - min*1.0)*m_RNG1.NextDouble() + min*1.0;
return Convert.ToInt64(rn);
}
/// <summary>
///
/// </summary>
public static Single Next(Single min, Single max)
{
if (max <= min)
{
string message = "Max must be greater than min.";
throw new ArgumentException(message);
}
double rn = (max*1.0 - min*1.0)*m_RNG1.NextDouble() + min*1.0;
return Convert.ToSingle(rn);
}
/// <summary>
///
/// </summary>
public static double Next(double min, double max)
{
if (max <= min)
{
string message = "Max must be greater than min.";
throw new ArgumentException(message);
}
double rn = (max - min)*m_RNG1.NextDouble() + min;
return rn;
}
/// <summary>
///
/// </summary>
public static DateTime Next(DateTime min, DateTime max)
{
if (max <= min)
{
string message = "Max must be greater than min.";
throw new ArgumentException(message);
}
long minTicks = min.Ticks;
long maxTicks = max.Ticks;
double rn = (Convert.ToDouble(maxTicks)
- Convert.ToDouble(minTicks))*m_RNG1.NextDouble()
+ Convert.ToDouble(minTicks);
return new DateTime(Convert.ToInt64(rn));
}
/// <summary>
///
/// </summary>
public static TimeSpan Next(TimeSpan min, TimeSpan max)
{
if (max <= min)
{
string message = "Max must be greater than min.";
throw new ArgumentException(message);
}
long minTicks = min.Ticks;
long maxTicks = max.Ticks;
double rn = (Convert.ToDouble(maxTicks)
- Convert.ToDouble(minTicks))*m_RNG1.NextDouble()
+ Convert.ToDouble(minTicks);
return new TimeSpan(Convert.ToInt64(rn));
}
/// <summary>
///
/// </summary>
public static double NextUniform()
{
return Next();
}
/// <summary>
///
///
/// </summary>
public static int NextEnum(Type enumType)
{
int[] values = (int[])Enum.GetValues(enumType);
int randomIndex = Next(0, values.Length);
return values[randomIndex];
}
#endregion
#region -- Exponential Deviates --
/// <summary>
///
///
/// </summary>
public static double NextExponential()
{
double dum = 0.0;
while (dum == 0.0)
dum=NextUniform();
return -1.0*System.Math.Log(dum, System.Math.E);
}
#endregion
#region -- Normal Deviates --
/// <summary>
///
///
/// </summary>
public static double NextNormal()
{
if (m_StoredUniformDeviateIsGood)
{
m_StoredUniformDeviateIsGood = false;
return m_StoredUniformDeviate;
}
else
{
double rsq = 0.0;
double v1 = 0.0, v2 = 0.0, fac = 0.0;
while (rsq >=1.0 || rsq == 0.0)
{
v1 = 2.0*Next() - 1.0;
v2 = 2.0*Next() - 1.0;
rsq = v1*v1 + v2*v2;
}
fac = System.Math.Sqrt(-2.0
*System.Math.Log(rsq, System.Math.E)/rsq);
m_StoredUniformDeviate = v1*fac;
m_StoredUniformDeviateIsGood = true;
return v2*fac;
}
}
#endregion
}
} |
|