RandomSharp 1.1.0

dotnet add package RandomSharp --version 1.1.0
                    
NuGet\Install-Package RandomSharp -Version 1.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="RandomSharp" Version="1.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RandomSharp" Version="1.1.0" />
                    
Directory.Packages.props
<PackageReference Include="RandomSharp" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add RandomSharp --version 1.1.0
                    
#r "nuget: RandomSharp, 1.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package RandomSharp@1.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=RandomSharp&version=1.1.0
                    
Install as a Cake Addin
#tool nuget:?package=RandomSharp&version=1.1.0
                    
Install as a Cake Tool

RandomSharp

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.

Description

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.

Features

  • 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

Overview

Easy-to-use Interface

RandomSharp offers a straightforward and intuitive interface, making it easy for developers to generate random data without extensive configuration or complex setup.

Extensibility

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.

DefaultRandomizer

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.

RNGRandomizer

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.

XorShiftRandomizer

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.

Weighted distribution

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.

Support for Nullable Values

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.

Usage

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.

Random booleans

	IRandomizer randomizer = new DefaultRandomizer();
	bool randomBoolean = randomizer.Boolean();
	bool? nullableRandomBoolean = randomizer.NullableBoolean();

Random numbers

	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);

Random dates

	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);

Random datetimes

	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);

Random enums

	enum DaysOfWeek { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }

	IRandomizer randomizer = new RNGRandomizer();
	DaysOfWeek randomEnumValue = randomizer.Enumeration<DaysOfWeek>();
	DaysOfWeek? nullableRandomEnumValue = randomizer.NullableEnumeration<DaysOfWeek>();

Random strings

	IRandomizer randomizer = new DefaultRandomizer();
	string randomString = randomizer.String(10);
	string randomStringWithCustomChars = randomizer.String(10, "ABC123");
	string? nullableRandomString = randomizer.NullableString(5, 10);

Random strings using StringCharacterType

	IRandomizer randomizer = new XorShiftRandomizer();
	int lenght = 30;
	string numeric = randomizer.String(lenght, StringCharacterType.Numeric);
	string uppercaseAlpha = randomizer.String(lenght, StringCharacterType.UppercaseAlpha);

Random nullable values

	public int CalculateSquare(int number)
	{
		return number * number;
	}

	IRandomizer randomizer = new RNGRandomizer();

	int inputNumber = randomizer.Int(1, 10);

	int? nullableSquare = randomizer.Nullable(inputNumber, CalculateSquare);

Weighted distribution

	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();
            }
        }

Implement your own generation algorithm

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;
        }
    }

Support

If you are having problems, please let us know by raising a new issue.

License

This project is licensed with the MIT license.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.0 288 6/7/2023
1.0.0 212 6/5/2023
0.9.0 216 6/7/2023