RandomSharp is a lightweight random data generator for .NET. It is designed to be easy to use, flexible and support different algorithms, allowing you to generate random data for testing, simulations, or any other scenario where you need randomized values. It provides a range of methods to generate different types of random data, making it suitable for a wide range of use cases.
RandomSharp is a .NET class library that provides a Randomizer
class, which is responsible for generating random data.
The Randomizer
class offers methods for generating random values of different types, such as booleans, integers, dates, and strings.
It also allows developers to implement their own generation algorithms if needed, includes options for generating nullable values,
generating random values from an enum, and generating random values within specific ranges.
- Target .NET Standard 2.0
- Generate random values for any .NET type.
- Support weighted distribution.
- Support for nullable values.
- Extensibility (Implement your own generation algorithm)
- Unit Test Project
RandomSharp offers a straightforward and intuitive interface, making it easy for developers to generate random data without extensive configuration or complex setup.
RandomSharp is designed to be extensible, allowing developers to implement their own generation algorithms if needed. This feature enables customization and adaptation to specific requirements by implementing a custom randomization algorithm.
RandomSharp implements a DefaultRandomizer
class that uses the System.Random class as the underlying generation algorithm.
The System.Random class generates pseudorandom numbers based on a seed value, making it suitable for scenarios where statistical randomness is sufficient.
The library also includes an RNGRandomizer
class that uses the System.Security.Cryptography.RNGCryptoServiceProvider class as the generation algorithm.
The RNGCryptoServiceProvider class utilizes a cryptographic random number generator that provides a higher level of randomness suitable for applications with stricter security requirements.
The library also includes an XorShiftRandomizer
class.
The XorShift algorithm is a pseudorandom number generator that uses bitwise exclusive OR (XOR) and shift operations to generate random numbers. It is known for its fast execution.
It allows you to generate random values based on a specific distribution with varying probabilities. It enables you to assign different weights or probabilities to each possible outcome, influencing the likelihood of generating certain values. This is useful in scenarios where you want to simulate real-world scenarios or emulate specific probability distributions.
The library includes support for generating nullable values. This is particularly useful when dealing with data types that can have null values, allowing developers to simulate various scenarios and test the behavior of their applications accordingly.
1- Clone or download the repository: To get started, clone or download the repository to your local machine.
2- Open the solution file in Visual Studio 2022: The solution file is located in the root directory of the project. Open this file in Visual Studio to start working with the project.
3- Build the project in release mode
4- Reference the class library dll in your application.
IRandomizer randomizer = new DefaultRandomizer();
bool randomBoolean = randomizer.Boolean();
bool? nullableRandomBoolean = randomizer.NullableBoolean();
IRandomizer randomizer = new XorShiftRandomizer();
int randomInt = randomizer.Int(10, 100);
int? nullableRandomInt = randomizer.NullableInt(10, 100);
double randomDouble = randomizer.Double(10.0, 100.0);
double? nullableRandomDouble = randomizer.NullableDouble(10, 100);
decimal randomDecimal = randomizer.Decimal(10.0M, 100.0M);
decimal? nullableRandomDecimal = randomizer.NullableDecimal(10.0M, 100.0M);
IRandomizer randomizer = new RNGRandomizer();
DateTime startDate = new DateTime(2010, 1, 1);
DateTime endDate = new DateTime(2022, 12, 31);
DateTime randomDate = randomizer.Date(startDate, endDate);
DateTime? nullableRandomDate = randomizer.NullableDate(startDate, endDate);
IRandomizer randomizer = new XorShiftRandomizer();
DateTime startDatetime = new DateTime(2010, 1, 1,0,0,0);
DateTime endDatetime = new DateTime(2022, 12, 31,12,30,40);
DateTime randomDatetime = randomizer.DateTime(startDatetime, endDatetime);
DateTime? nullableRandomDatetime = randomizer.NullableDateTime(startDatetime, endDatetime);
enum DaysOfWeek { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }
IRandomizer randomizer = new RNGRandomizer();
DaysOfWeek randomEnumValue = randomizer.Enumeration<DaysOfWeek>();
DaysOfWeek? nullableRandomEnumValue = randomizer.NullableEnumeration<DaysOfWeek>();
IRandomizer randomizer = new DefaultRandomizer();
string randomString = randomizer.String(10);
string randomStringWithCustomChars = randomizer.String(10, "ABC123");
string? nullableRandomString = randomizer.NullableString(5, 10);
IRandomizer randomizer = new XorShiftRandomizer();
int lenght = 30;
string numeric = randomizer.String(lenght, StringCharacterType.Numeric);
string uppercaseAlpha = randomizer.String(lenght, StringCharacterType.UppercaseAlpha);
public int CalculateSquare(int number)
{
return number * number;
}
IRandomizer randomizer = new RNGRandomizer();
int inputNumber = randomizer.Int(1, 10);
int? nullableSquare = randomizer.Nullable(inputNumber, CalculateSquare);
public class Employee
{
public int yearsOfExperience { get; set; }
public ExperienceLevel ExperienceLevel { get; set; }
}
public enum ExperienceLevel { Junior, Senior, Executive }
IRandomizer randomizer = new RNGRandomizer();
var experienceLevels = Enum.GetValues<ExperienceLevel>();
// 55% Junior, 35% Senior, 10% Executive
double[] weights = new List<double>() { 0.55, 0.35, 0.1 }.ToArray();
var oneEmployee = new Employee
{
yearsOfExperience = randomizer.Int(0, 25),
ExperienceLevel = randomizer.Random(experienceLevels, weights)
};
IList<Employee> employees = new List<Employee>();
for (int i = 0; i < 100; i++)
{
var employee = new Employee
{
yearsOfExperience = randomizer.Int(0, 25),
ExperienceLevel = randomizer.Random(experienceLevels, weights)
};
employees.Add(employee);
}
// Count distribution
var group = employees.GroupBy(e => e.ExperienceLevel).ToDictionary(e => e.Key, e => e.Select(a => a.yearsOfExperience).ToList());
Here's an example to illustrate a complex scenario of random weighted distribution.
In this example, we have the ExperienceLevel enumeration representing different levels of experience. We calculate the weights of each experience level based on the given yearsOfExperience
.
IRandomizer randomizer = new RNGRandomizer();
var experienceLevels = Enum.GetValues<ExperienceLevel>();
var yearsOfExperience = randomizer.Int(0, 25);
double[] weights = CalulateWeights(yearsOfExperience); // calculates ExperienceLevel weights based on yearsOfExperience
var employee = new Employee
{
yearsOfExperience = yearsOfExperience,
ExperienceLevel = randomizer.Random(experienceLevels, weights)
};
public static double[] CalulateWeights(int yearsOfExperience)
{
if (yearsOfExperience <= 2) // years <= 2 : 100% Junior
{
return new List<double>() { 1, 0, 0 }.ToArray();
}
if (yearsOfExperience <= 5) // 2 < years <= 5 : 95% Junior, 5% Senior
{
return new List<double>() { 0.95, 0.05, 0 }.ToArray();
}
else if (yearsOfExperience <= 10) // 5 < years <= 10 : 10% Junior, 90% Senior
{
return new List<double>() { 0.1, 0.9, 0 }.ToArray();
}
else if (yearsOfExperience <= 15) // 10 < years <= 15 : 95% Senior, 5% Executive
{
return new List<double>() { 0, 0.95, 0.05 }.ToArray();
}
else if (yearsOfExperience <= 20) // 15 < years <= 20 : 10% Senior, 90% Executive
{
return new List<double>() { 0, 0.1, 0.9 }.ToArray();
}
else
{
// 20 < years : 100% Executive
return new List<double>() { 0, 0, 1 }.ToArray();
}
}
You can Implement your own custom generation algorithm within the library. It provides flexibility and control over how the random values are generated for different types. Instead of relying on the default algorithms provided by the library, you have the option to define and use your own logic for generating random values. You can design an algorithm that aligns with your specific application or scenario, taking into account factors such as data distribution, range constraints, or any other specific requirements. To implement your own generation algorithm, you can create a new class that implements the Randomizer class with your desired algorithm, and then use an instance of that class instead of other Randomizer implementations.
These abstract methods must be implemented
protected abstract bool InternalBoolean();
protected abstract int InternalInt(int maxExclusive);
protected abstract int InternalInt(int minInclusive, int maxExclusive);
protected abstract double InternalDouble(double min, double max);
protected abstract double InternalDouble();
Here is an example of a custom implementation based on Lagged Fibonacci Generator
public class LFGRandomizer : Randomizer, IRandomizer
{
protected const int Lag1 = 23;
protected const int Lag2 = 48;
protected ulong[] state;
protected int index;
public LFGRandomizer()
{
// Initialize the state and index
state = new ulong[Lag2];
index = 0;
// Seed the initial values
InitSeed();
}
protected void InitSeed()
{
// You can modify this to use a different seed generation mechanism
for (int i = 0; i < Lag2; i++)
{
state[i] = (ulong)System.DateTime.Now.Ticks;
}
}
protected ulong LFGUInt64()
{
ulong next = state[index] + state[(index - Lag1 + Lag2) % Lag2];
state[index] = next;
index = (index + 1) % Lag2;
return next;
}
protected override bool InternalBoolean()
{
return LFGUInt64() % 2 == 0;
}
protected override int InternalInt(int maxExclusive)
{
return InternalInt(0, maxExclusive);
}
protected override int InternalInt(int minInclusive, int maxExclusive)
{
checked
{
double scaleFactor = ScaleFactor();
return (int)(minInclusive + (maxExclusive - minInclusive) * scaleFactor);
}
}
protected override double InternalDouble(double min, double max)
{
return InternalDouble() * (max - min) + min;
}
protected override double InternalDouble()
{
return ScaleFactor();
}
protected double ScaleFactor()
{
const double scale = 1.0 / uint.MaxValue;
return LFGUInt64() * scale;
}
}
If you are having problems, please let us know by raising a new issue.
This project is licensed with the MIT license.